mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
clean up some includes in pcb_reader
- fix deadlock
This commit is contained in:
parent
fb99dfc915
commit
3348cc9c47
7 changed files with 277 additions and 224 deletions
|
@ -2,13 +2,17 @@
|
|||
#define EXPORTMGR_H
|
||||
|
||||
#include "exporter.h"
|
||||
#include "navmesh_exporter.h"
|
||||
#include "obj_exporter.h"
|
||||
#include "threadpool.h"
|
||||
|
||||
class ExportMgr
|
||||
{
|
||||
public:
|
||||
ExportMgr(){}
|
||||
ExportMgr( unsigned int maxJobs = 0 )
|
||||
{
|
||||
m_threadpool.addWorkers( maxJobs );
|
||||
}
|
||||
~ExportMgr()
|
||||
{
|
||||
waitForTasks();
|
||||
|
@ -20,6 +24,10 @@ public:
|
|||
{
|
||||
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 )
|
||||
|
@ -28,6 +36,10 @@ public:
|
|||
{
|
||||
m_threadpool.queue( [zoneName, group](){ ObjExporter::exportGroup( zoneName, group ); } );
|
||||
}
|
||||
if( exportFileTypes & ExportFileType::Navmesh )
|
||||
{
|
||||
m_threadpool.queue( [zoneName, group](){ NavmeshExporter::exportGroup( zoneName, group ); } );
|
||||
}
|
||||
}
|
||||
|
||||
void waitForTasks()
|
||||
|
|
|
@ -295,7 +295,7 @@ struct LGB_GROUP
|
|||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
std::cout << name << " " << e.what() << std::endl;
|
||||
std::cout << ( name + " " + e.what() + "\n" );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,12 +29,6 @@
|
|||
#include <ExdCat.h>
|
||||
#include <Exd.h>
|
||||
|
||||
#include <condition_variable>
|
||||
|
||||
#include <recastnavigation/Recast/Include/Recast.h>
|
||||
#include <recastnavigation/Recast/Include/RecastAlloc.h>
|
||||
|
||||
|
||||
// garbage to ignore models
|
||||
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;
|
||||
uint32_t zoneId;
|
||||
|
||||
|
||||
std::set< std::string > zoneDumpList;
|
||||
|
||||
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 = std::string( "ffxiv/" ) + path;
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
@ -145,7 +140,7 @@ int main( int argc, char* argv[] )
|
|||
}
|
||||
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;
|
||||
}
|
||||
ExportMgr exportMgr;
|
||||
|
@ -221,211 +216,205 @@ int main( int argc, char* argv[] )
|
|||
uint32_t max_index = 0;
|
||||
int totalModels = 0;
|
||||
|
||||
|
||||
|
||||
auto buildModelEntry = [ & ]( std::shared_ptr< PCB_FILE > pPcbFile, ExportedGroup& exportedGroup,
|
||||
const std::string& name, const std::string& groupName,
|
||||
const vec3* scale = nullptr,
|
||||
const vec3* rotation = nullptr,
|
||||
const vec3* translation = nullptr,
|
||||
const SGB_MODEL_ENTRY* pSgbEntry = nullptr )
|
||||
{
|
||||
|
||||
auto& pcb_file = *pPcbFile.get();
|
||||
|
||||
auto buildModelEntry = [ & ]( std::shared_ptr< PCB_FILE > pPcbFile, ExportedGroup& exportedGroup,
|
||||
const std::string& name, const std::string& groupName,
|
||||
const vec3* scale = nullptr,
|
||||
const vec3* rotation = nullptr,
|
||||
const vec3* translation = nullptr,
|
||||
const SGB_MODEL_ENTRY* pSgbEntry = nullptr )
|
||||
ExportedModel model;
|
||||
model.name = name + "_" + std::to_string( totalModels++ );
|
||||
model.meshes.resize( pcb_file.entries.size() );
|
||||
|
||||
uint32_t meshCount = 0;
|
||||
for( const auto& entry : pcb_file.entries )
|
||||
{
|
||||
|
||||
auto& pcb_file = *pPcbFile.get();
|
||||
ExportedMesh mesh;
|
||||
|
||||
ExportedModel model;
|
||||
model.name = name + "_" + std::to_string( totalModels++ );
|
||||
model.meshes.resize( pcb_file.entries.size() );
|
||||
mesh.verts.resize( ( entry.header.num_vertices + entry.header.num_v16 ) * 3 );
|
||||
mesh.indices.resize( entry.header.num_indices * 3 );
|
||||
|
||||
uint32_t groupCount = 0;
|
||||
for( const auto& entry : pcb_file.entries )
|
||||
float x_base = abs( float( entry.header.x1 - entry.header.x ) );
|
||||
float y_base = abs( float( entry.header.y1 - entry.header.y ) );
|
||||
float z_base = abs( float( entry.header.z1 - entry.header.z ) );
|
||||
|
||||
auto makeTranslation = [ & ]( vec3& v )
|
||||
{
|
||||
ExportedMesh mesh;
|
||||
|
||||
int verts = 0;
|
||||
int indices = 0;
|
||||
mesh.verts.resize( ( entry.header.num_vertices + entry.header.num_v16 ) * 3 );
|
||||
mesh.indices.resize( entry.header.num_indices * 3 );
|
||||
|
||||
float x_base = abs( float( entry.header.x1 - entry.header.x ) );
|
||||
float y_base = abs( float( entry.header.y1 - entry.header.y ) );
|
||||
float z_base = abs( float( entry.header.z1 - entry.header.z ) );
|
||||
|
||||
auto makeTranslation = [ & ]( vec3& v )
|
||||
if( pSgbEntry )
|
||||
{
|
||||
if( pSgbEntry )
|
||||
v.x *= pSgbEntry->header.scale.x;
|
||||
v.y *= pSgbEntry->header.scale.y;
|
||||
v.z *= pSgbEntry->header.scale.z;
|
||||
|
||||
v = v * matrix4::rotateX( pSgbEntry->header.rotation.x );
|
||||
v = v * matrix4::rotateY( pSgbEntry->header.rotation.y );
|
||||
v = v * matrix4::rotateZ( pSgbEntry->header.rotation.z );
|
||||
|
||||
v.x += pSgbEntry->header.translation.x;
|
||||
v.y += pSgbEntry->header.translation.y;
|
||||
v.z += pSgbEntry->header.translation.z;
|
||||
}
|
||||
|
||||
if( scale )
|
||||
{
|
||||
v.x *= scale->x;
|
||||
v.y *= scale->y;
|
||||
v.z *= scale->z;
|
||||
|
||||
v = v * matrix4::rotateX( rotation->x );
|
||||
v = v * matrix4::rotateY( rotation->y );
|
||||
v = v * matrix4::rotateZ( rotation->z );
|
||||
|
||||
v.x += translation->x;
|
||||
v.y += translation->y;
|
||||
v.z += translation->z;
|
||||
}
|
||||
|
||||
};
|
||||
int verts = 0;
|
||||
int indices = 0;
|
||||
|
||||
for( auto& vertex : entry.data.vertices )
|
||||
{
|
||||
vec3 v( vertex.x, vertex.y, vertex.z );
|
||||
makeTranslation( v );
|
||||
|
||||
mesh.verts[ verts++ ] = v.x;
|
||||
mesh.verts[ verts++ ] = v.y;
|
||||
mesh.verts[ verts++ ] = v.z;
|
||||
}
|
||||
|
||||
for( const auto& link : entry.data.vertices_i16 )
|
||||
{
|
||||
vec3 v( float( link.x ) / 0xFFFF, float( link.y ) / 0xFFFF, float( link.z ) / 0xFFFF );
|
||||
|
||||
v.x = v.x * x_base + entry.header.x;
|
||||
v.y = v.y * y_base + entry.header.y;
|
||||
v.z = v.z * z_base + entry.header.z;
|
||||
|
||||
makeTranslation( v );
|
||||
|
||||
mesh.verts[ verts++ ] = v.x;
|
||||
mesh.verts[ verts++ ] = v.y;
|
||||
mesh.verts[ verts++ ] = v.z;
|
||||
}
|
||||
|
||||
for( const auto& index : entry.data.indices )
|
||||
{
|
||||
mesh.indices[ indices++ ] = index.index[ 0 ];
|
||||
mesh.indices[ indices++ ] = index.index[ 1 ];
|
||||
mesh.indices[ indices++ ] = index.index[ 2 ];
|
||||
// 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();
|
||||
model.meshes[ meshCount++ ] = mesh;
|
||||
}
|
||||
exportedGroup.models[model.name] = model;
|
||||
};
|
||||
ExportedGroup exportedTerrainGroup;
|
||||
exportedTerrainGroup.name = zoneName + "_terrain";
|
||||
for( const auto& fileName : stringList )
|
||||
{
|
||||
if( auto pPcbFile = pCache->getPcbFile( fileName ) )
|
||||
buildModelEntry( pPcbFile, exportedTerrainGroup, fileName, zoneName );
|
||||
}
|
||||
exportMgr.exportGroup( zoneName, exportedTerrainGroup, ( ExportFileType )exportFileType );
|
||||
|
||||
for( const auto& lgb : lgbList )
|
||||
{
|
||||
for( const auto& group : lgb.groups )
|
||||
{
|
||||
ExportedGroup exportedGroup;
|
||||
exportedGroup.name = group.name;
|
||||
|
||||
max_index = 0;
|
||||
|
||||
//std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n";
|
||||
for( const auto& pEntry : group.entries )
|
||||
{
|
||||
std::string fileName( "" );
|
||||
fileName.resize( 256 );
|
||||
|
||||
// write files
|
||||
auto pcbTransformModel = [&]( const std::string& fileName, const vec3* scale, const vec3* rotation,
|
||||
const vec3* translation, const SGB_MODEL_ENTRY* pModel = nullptr )-> bool
|
||||
{
|
||||
if( auto pPcbFile = pCache->getPcbFile( fileName ) )
|
||||
{
|
||||
v.x *= pSgbEntry->header.scale.x;
|
||||
v.y *= pSgbEntry->header.scale.y;
|
||||
v.z *= pSgbEntry->header.scale.z;
|
||||
|
||||
v = v * matrix4::rotateX( pSgbEntry->header.rotation.x );
|
||||
v = v * matrix4::rotateY( pSgbEntry->header.rotation.y );
|
||||
v = v * matrix4::rotateZ( pSgbEntry->header.rotation.z );
|
||||
|
||||
v.x += pSgbEntry->header.translation.x;
|
||||
v.y += pSgbEntry->header.translation.y;
|
||||
v.z += pSgbEntry->header.translation.z;
|
||||
buildModelEntry( pPcbFile, exportedGroup, fileName, group.name, scale, rotation, translation, pModel );
|
||||
}
|
||||
|
||||
if( scale )
|
||||
{
|
||||
v.x *= scale->x;
|
||||
v.y *= scale->y;
|
||||
v.z *= scale->z;
|
||||
|
||||
v = v * matrix4::rotateX( rotation->x );
|
||||
v = v * matrix4::rotateY( rotation->y );
|
||||
v = v * matrix4::rotateZ( rotation->z );
|
||||
|
||||
v.x += translation->x;
|
||||
v.y += translation->y;
|
||||
v.z += translation->z;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
for( auto& vertex : entry.data.vertices )
|
||||
switch( pEntry->getType() )
|
||||
{
|
||||
vec3 v( vertex.x, vertex.y, vertex.z );
|
||||
makeTranslation( v );
|
||||
|
||||
mesh.verts[ verts++ ] = v.x;
|
||||
mesh.verts[ verts++ ] = v.y;
|
||||
mesh.verts[ verts++ ] = v.z;
|
||||
}
|
||||
|
||||
for( const auto& link : entry.data.vertices_i16 )
|
||||
{
|
||||
vec3 v( float( link.x ) / 0xFFFF, float( link.y ) / 0xFFFF, float( link.z ) / 0xFFFF );
|
||||
|
||||
v.x = v.x * x_base + entry.header.x;
|
||||
v.y = v.y * y_base + entry.header.y;
|
||||
v.z = v.z * z_base + entry.header.z;
|
||||
|
||||
makeTranslation( v );
|
||||
|
||||
mesh.verts[ verts++ ] = v.x;
|
||||
mesh.verts[ verts++ ] = v.y;
|
||||
mesh.verts[ verts++ ] = v.z;
|
||||
}
|
||||
|
||||
//fprintf( fp_out, "g %s_", (name2 + "_" + std::to_string( groupCount++ )).c_str() );
|
||||
for( const auto& index : entry.data.indices )
|
||||
{
|
||||
mesh.indices[ indices++ ] = index.index[ 0 ];
|
||||
mesh.indices[ indices++ ] = index.index[ 1 ];
|
||||
mesh.indices[ indices++ ] = index.index[ 2 ];
|
||||
// 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();
|
||||
model.meshes.push_back( mesh );
|
||||
}
|
||||
exportedGroup.models[model.name] = model;
|
||||
};
|
||||
ExportedGroup exportedTerrainGroup;
|
||||
exportedTerrainGroup.name = zoneName;
|
||||
for( const auto& fileName : stringList )
|
||||
{
|
||||
if( auto pPcbFile = pCache->getPcbFile( fileName ) )
|
||||
buildModelEntry( pPcbFile, exportedTerrainGroup, fileName, zoneName );
|
||||
}
|
||||
|
||||
for( const auto& lgb : lgbList )
|
||||
{
|
||||
for( const auto& group : lgb.groups )
|
||||
{
|
||||
ExportedGroup exportedGroup;
|
||||
exportedGroup.name = group.name;
|
||||
|
||||
max_index = 0;
|
||||
|
||||
//std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n";
|
||||
for( const auto& pEntry : group.entries )
|
||||
{
|
||||
std::string fileName( "" );
|
||||
fileName.resize( 256 );
|
||||
|
||||
// write files
|
||||
auto writeOutput = [&](const std::string& fileName, const vec3* scale, const vec3* rotation,
|
||||
const vec3* translation, const SGB_MODEL_ENTRY* pModel = nullptr)->bool
|
||||
case LgbEntryType::BgParts:
|
||||
{
|
||||
if( auto pPcbFile = pCache->getPcbFile( fileName ) )
|
||||
{
|
||||
buildModelEntry( pPcbFile, exportedGroup, fileName, group.name, scale, rotation, translation, pModel );
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto pBgParts = static_cast<LGB_BGPARTS_ENTRY*>(pEntry.get());
|
||||
fileName = pBgParts->collisionFileName;
|
||||
pcbTransformModel( fileName, &pBgParts->header.scale, &pBgParts->header.rotation,
|
||||
&pBgParts->header.translation );
|
||||
}
|
||||
break;
|
||||
|
||||
switch( pEntry->getType() )
|
||||
// gimmick entry
|
||||
case LgbEntryType::Gimmick:
|
||||
{
|
||||
case LgbEntryType::BgParts:
|
||||
auto pGimmick = static_cast<LGB_GIMMICK_ENTRY*>( pEntry.get() );
|
||||
if( auto pSgbFile = pCache->getSgbFile( pGimmick->gimmickFileName ) )
|
||||
{
|
||||
auto pBgParts = static_cast<LGB_BGPARTS_ENTRY*>(pEntry.get());
|
||||
fileName = pBgParts->collisionFileName;
|
||||
writeOutput( fileName, &pBgParts->header.scale, &pBgParts->header.rotation,
|
||||
&pBgParts->header.translation );
|
||||
}
|
||||
break;
|
||||
|
||||
// gimmick entry
|
||||
case LgbEntryType::Gimmick:
|
||||
{
|
||||
auto pGimmick = static_cast<LGB_GIMMICK_ENTRY*>(pEntry.get());
|
||||
if (auto pSgbFile = pCache->getSgbFile(pGimmick->gimmickFileName))
|
||||
const auto& sgbFile = *pSgbFile;
|
||||
for( const auto& group : sgbFile.entries )
|
||||
{
|
||||
const auto& sgbFile = *pSgbFile;
|
||||
for (const auto& group : sgbFile.entries)
|
||||
for( const auto& pEntry : group.entries )
|
||||
{
|
||||
for (const auto& pEntry : group.entries)
|
||||
{
|
||||
auto pModel = dynamic_cast<SGB_MODEL_ENTRY*>(pEntry.get());
|
||||
fileName = pModel->collisionFileName;
|
||||
writeOutput( fileName, &pGimmick->header.scale, &pGimmick->header.rotation,
|
||||
&pGimmick->header.translation, pModel );
|
||||
}
|
||||
auto pModel = dynamic_cast< SGB_MODEL_ENTRY* >( pEntry.get() );
|
||||
fileName = pModel->collisionFileName;
|
||||
pcbTransformModel( fileName, &pGimmick->header.scale, &pGimmick->header.rotation,
|
||||
&pGimmick->header.translation, pModel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case LgbEntryType::EventObject:
|
||||
{
|
||||
writeOutput( fileName, &pEntry->header.scale, &pEntry->header.rotation, &pEntry->header.translation );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
exportMgr.exportGroup( zoneName, exportedGroup, ( ExportFileType )exportFileType );
|
||||
//exportedZone.groups.emplace( group.name, exportedGroup );
|
||||
}
|
||||
}
|
||||
//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 >(
|
||||
std::chrono::high_resolution_clock::now() - entryStartTime ).count() << " seconds\n";
|
||||
case LgbEntryType::EventObject:
|
||||
{
|
||||
pcbTransformModel( fileName, &pEntry->header.scale, &pEntry->header.rotation, &pEntry->header.translation );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
exportMgr.exportGroup( zoneName, exportedGroup, ( ExportFileType )exportFileType );
|
||||
//exportedZone.groups.emplace( group.name, exportedGroup );
|
||||
}
|
||||
}
|
||||
//exportMgr.exportZone( exportedZone, ( ExportFileType )exportFileType );
|
||||
|
||||
|
||||
printf( "Exported %s in %u seconds \n",
|
||||
zoneName.c_str(),
|
||||
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::high_resolution_clock::now() - entryStartTime ) );
|
||||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
std::cout << "[Error] " << e.what() << std::endl;
|
||||
std::cout << "[Error] "
|
||||
<< "Unable to extract collision data.\n"
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
|
||||
printf( ( std::string( e.what() ) + "\n" ).c_str() );
|
||||
printf( "Unable to extract collision data.\n" );
|
||||
printf( "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\"\n" );
|
||||
}
|
||||
}
|
||||
exportMgr.waitForTasks();
|
||||
std::cout << "\n\n\n";
|
||||
|
||||
std::cout << "\n\n\n[Success] Finished all tasks in " <<
|
||||
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::high_resolution_clock::now() - startTime ).count()
|
||||
<< " seconds\n";
|
||||
printf( "Finished all tasks in %u seconds\n",
|
||||
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::high_resolution_clock::now() - startTime ).count() );
|
||||
|
||||
getchar();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef OBJ_EXPORTER_H
|
||||
#define OBJ_EXPORTER_H
|
||||
#ifndef NAVMESH_EXPORTER_H
|
||||
#define NAVMESH_EXPORTER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
@ -10,7 +10,12 @@
|
|||
|
||||
#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:
|
||||
static void exportZone( const ExportedZone& zone )
|
||||
|
@ -20,8 +25,9 @@ public:
|
|||
auto fileName = zone.name + ".obj";
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << ( "Finished exporting " + fileName + " in " +
|
||||
std::to_string( std::chrono::duration_cast< std::chrono::seconds >( end - start ).count() ) + " seconds\n" );
|
||||
printf( "[Navmesh] Finished exporting %s in %u ms\n",
|
||||
fileName,
|
||||
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
|
||||
}
|
||||
|
||||
static void exportGroup( const std::string& zoneName, const ExportedGroup& group )
|
||||
|
@ -32,8 +38,9 @@ public:
|
|||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << ( "Finished exporting " + fileName + " in " +
|
||||
std::to_string( std::chrono::duration_cast< std::chrono::seconds >( end - start ).count() ) + " seconds\n" );
|
||||
printf( "[Navmesh] Finished exporting %s in %u ms\n",
|
||||
fileName,
|
||||
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
|
||||
}
|
||||
private:
|
||||
static void exportGroup( const ExportedGroup& group, std::ofstream& of, int& indicesOffset, int& modelCount )
|
||||
|
|
|
@ -1,22 +1,38 @@
|
|||
#ifndef OBJ_EXPORTER_H
|
||||
#define OBJ_EXPORTER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <experimental/filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "exporter.h"
|
||||
|
||||
|
||||
class ObjExporter : public Exporter
|
||||
{
|
||||
public:
|
||||
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 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 );
|
||||
int indicesOffset = 0;
|
||||
int meshesCount = 0;
|
||||
|
@ -34,15 +50,29 @@ public:
|
|||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << ( "Finished exporting " + fileName + " in " +
|
||||
std::to_string( std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() ) + "ms \n" );
|
||||
printf( "[Obj] Finished exporting %s in %u ms\n",
|
||||
fileName,
|
||||
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
|
||||
}
|
||||
|
||||
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 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 );
|
||||
int indicesOffset = 0;
|
||||
int modelCount = 0;
|
||||
|
@ -57,42 +87,47 @@ public:
|
|||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << ( "Finished exporting " + fileName + " in " +
|
||||
std::to_string( std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() ) + "ms\n" );
|
||||
printf( "[Obj] Finished exporting %s in %u ms\n",
|
||||
fileName.c_str(),
|
||||
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
|
||||
}
|
||||
private:
|
||||
static void exportGroup( const ExportedGroup& group, std::ofstream& of, int& indicesOffset, int& 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 )
|
||||
{
|
||||
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;
|
||||
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 << (
|
||||
"v " + std::to_string( mesh.verts[ i ] ) + " " +
|
||||
std::to_string( mesh.verts[ i + 1 ] ) + " " +
|
||||
std::to_string( mesh.verts[ i + 2 ] ) + "\n"
|
||||
);
|
||||
of << "v " <<
|
||||
std::to_string( mesh.verts[ i ] ) << ' ' <<
|
||||
std::to_string( mesh.verts[ i + 1 ] ) << ' ' <<
|
||||
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 << (
|
||||
"f " + std::to_string( mesh.indices[ i ] + indicesOffset + 1 ) + " " +
|
||||
std::to_string( mesh.indices[i + 1] + indicesOffset + 1 ) + " " +
|
||||
std::to_string( mesh.indices[i + 2] + indicesOffset + 1 ) + "\n"
|
||||
);
|
||||
of << "f " <<
|
||||
std::to_string( mesh.indices[ i ] + indicesOffset + 1 ) << ' ' <<
|
||||
std::to_string( mesh.indices[ i + 1 ] + indicesOffset + 1 ) << ' ' +
|
||||
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
|
||||
|
|
|
@ -213,7 +213,7 @@ struct SGB_FILE
|
|||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
std::cout << e.what() << "\n";
|
||||
std::cout << ( std::string( e.what() ) + "\n" );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,12 +13,9 @@
|
|||
class ThreadPool
|
||||
{
|
||||
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()
|
||||
|
@ -26,6 +23,17 @@ public:
|
|||
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&() > >
|
||||
std::future< Ret > queue( Func&& f )
|
||||
{
|
||||
|
@ -50,10 +58,12 @@ public:
|
|||
|
||||
bool complete()
|
||||
{
|
||||
std::unique_lock lock( m_mutex );
|
||||
for( auto&& worker : m_workers )
|
||||
{
|
||||
m_pendingJobs.push_back( {} );
|
||||
std::scoped_lock lock( m_mutex );
|
||||
for( auto&& worker : m_workers )
|
||||
{
|
||||
m_pendingJobs.push_back( {} );
|
||||
}
|
||||
}
|
||||
m_cv.notify_all();
|
||||
m_workers.clear();
|
||||
|
|
Loading…
Add table
Reference in a new issue