diff --git a/src/tools/pcb_reader/lgb.h b/src/tools/pcb_reader/lgb.h index 091ae3b0..a4ef3977 100644 --- a/src/tools/pcb_reader/lgb.h +++ b/src/tools/pcb_reader/lgb.h @@ -1,6 +1,8 @@ #ifndef _LGB_H #define _LGB_H +#include "matrix4.h" +#include "vec3.h" #include #include #include @@ -16,11 +18,6 @@ struct LGB_FILE_HEADER; struct LGB_GROUP; struct LGB_GROUP_HEADER; -struct vec3 -{ - float x, y, z; -}; - enum class LgbEntryType : uint32_t { BgParts = 1, @@ -174,7 +171,7 @@ struct LGB_GROUP entries.resize(header.entryCount); //std::cout << name << std::endl; auto entriesOffset = offset + header.entriesOffset; - for( auto i = 0; i < header.entryCount; ++i) + for( auto i = 0; i < header.entryCount; ++i ) { auto entryOffset = entriesOffset + *reinterpret_cast(buf + (entriesOffset + i * 4)); @@ -190,10 +187,14 @@ struct LGB_GROUP { entries[i] = std::make_shared(buf, entryOffset); } + else + { + entries[i] = nullptr; + } } catch (std::exception& e) { - std::cout << e.what() << std::endl; + std::cout << name << " " << e.what() << std::endl; } } }; diff --git a/src/tools/pcb_reader/main.cpp b/src/tools/pcb_reader/main.cpp index 3cb02fed..52b2686a 100644 --- a/src/tools/pcb_reader/main.cpp +++ b/src/tools/pcb_reader/main.cpp @@ -29,13 +29,12 @@ std::vector loadDir(const std::string& dir) return files; } -int parseBlockEntry( char* data, std::vector& entries, int gOff, uint32_t& groupCount, LGB_BGPARTS_ENTRY& bgParts ) +int parseBlockEntry( char* data, std::vector& entries, int gOff ) { int offset = 0; bool isgroup = true; while( isgroup ) { - groupCount++; PCB_BLOCK_ENTRY block_entry; memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) ); isgroup = block_entry.header.type == 0x30 ? true : false; @@ -44,13 +43,13 @@ int parseBlockEntry( char* data, std::vector& entries, int gOff if( isgroup ) { - parseBlockEntry( data + offset + 0x30, entries, gOff + offset, groupCount, bgParts ); + parseBlockEntry( data + offset + 0x30, entries, gOff + offset ); offset += block_entry.header.group_size; } else { - //printf( "\tnum_v16: %i, num_indices: %i, num_vertices: %i\n\n", - // block_entry.header.num_v16, block_entry.header.num_indices, block_entry.header.num_vertices ); + /* printf( "\tnum_v16: %i, num_indices: %i, num_vertices: %i\n\n", + block_entry.header.num_v16, block_entry.header.num_indices, block_entry.header.num_vertices );*/ int doffset = sizeof( block_entry.header ) + offset; uint16_t block_size = sizeof( block_entry.header ) + block_entry.header.num_vertices * 3 * 4 + @@ -80,39 +79,35 @@ int parseBlockEntry( char* data, std::vector& entries, int gOff doffset += size_indexbuffer; } entries.push_back( block_entry ); - - //printf( "Vertices: \n" ); - for( auto& entry1 : block_entry.data.vertices ) - { - // printf( "\t %f, %f, %f \n", - // entry1.x, entry1.y, entry1.z ); - } - - float x_base = abs( float( block_entry.header.x1 - block_entry.header.x ) ); - float y_base = abs( float( block_entry.header.y1 - block_entry.header.y ) ); - float z_base = abs( float( block_entry.header.z1 - block_entry.header.z ) ); - - //printf( "Vertices I16: \n" ); - for( auto& entry1 : block_entry.data.vertices_i16 ) - { - uint16_t var1 = entry1.x; - uint16_t var2 = entry1.y; - uint16_t var3 = entry1.z; - float x = ( var1 ); - float y = ( var2 ); - float z = ( var3 ); - //printf( "\t%f, ", ( x / 0xFFFF ) * x_base + block_entry.header.x ); - //printf( "%f, ", ( y / 0xFFFF ) * y_base + block_entry.header.y ); - //printf( "%f ", ( z / 0xFFFF ) * z_base + block_entry.header.z ); - //printf( "\n" ); - - } } } return 0; } +void toFile(const std::string& fileName, const std::vector& vertices, const std::vector& indices) +{ + auto fp_out = fopen(fileName.c_str(), "w"); + if (fp_out) + { + fprintf(fp_out, "\n"); + fclose(fp_out); + } + fp_out = fopen(fileName.c_str(), "ab+"); + if (fp_out) + { + for (const auto& v : vertices) + { + fprintf(fp_out, "v %f %f %f\n", v.x, v.y, v.z); + } + for (auto i = 2002; i < indices.size(); i += 3) + { + fprintf(fp_out, "f %i %i %i\n", indices[i], indices[i + 1], indices[i + 2]); + } + fclose(fp_out); + } +} + int main() { char *data; @@ -126,167 +121,132 @@ int main() std::cout << "Loaded " << lgbFiles.size() << " LGB files" << std::endl; - uint64_t vertexCount = 0; std::map groupCounts; + std::map pcbFiles; + + int total_vertices = 0; + int total_indices = 0; + int max_index = 0; + + std::vector vertices; + std::vector indices; + for (const auto& pair : lgbFiles) { + std::cout << "FILE " << pair.first << "\n"; for (const auto& group : pair.second.groups) { + uint32_t groupEntryCount = 0; uint32_t bgPartsCount = 0; - std::cout << group.name << "\n"; + //std::cout << "GROUP " << group.name << "\n"; for (auto entry : group.entries) { if (dynamic_cast(entry.get())) bgPartsCount++; } - for (auto entry : group.entries) + for (auto pEntry : group.entries) { - auto bgParts = dynamic_cast(entry.get()); - if (!bgParts) + if (!pEntry) continue; - const auto& filename = bgParts->collisionFileName; - std::cout << filename << std::endl; - //std::string filename( "f1h0_s_rof0003.pcb" ); - //std::string filename("tr0924.pcb"); - FILE *fp = nullptr; - fp = fopen(filename.c_str(), "rb"); - if (fp == nullptr) + auto pBgParts = dynamic_cast(pEntry.get()); + + if (!pBgParts || pBgParts->collisionFileName.empty()) + continue; + + auto filename = pBgParts->collisionFileName; + if(!groupCounts[filename]) + std::cout << "GROUP " << group.name << " " << pBgParts->collisionFileName << "\n"; + + PCB_FILE pcb_file = PCB_FILE(); + if(pcbFiles.find(filename) == pcbFiles.end()) { - return 0; + FILE *fp = nullptr; + fp = fopen(filename.c_str(), "rb"); + if (fp == nullptr) + return 0; + + fseek(fp, 0, SEEK_END); + int32_t size = ftell(fp); + data = new char[size]; + rewind(fp); + fread(data, 1, size, fp); + fclose(fp); + + memcpy(&pcb_file.header, data, sizeof(pcb_file.header)); + auto offset = sizeof(pcb_file.header); + try + { + parseBlockEntry(data + offset, pcb_file.entries, offset); + } + catch(std::exception& e) + { + std::cout << "Unable to parse " << filename << " " << e.what() << "\n"; + } + } + else + { + pcb_file = pcbFiles[filename]; } - fseek(fp, 0, SEEK_END); - int32_t size = ftell(fp); - data = new char[size]; - rewind(fp); - fread(data, sizeof(char), size, fp); - fclose(fp); + for( auto &entry : pcb_file.entries ) + { + total_vertices += entry.header.num_vertices; + total_vertices += entry.header.num_v16; - PCB_FILE pcb_file; - memcpy(&pcb_file.header, data, sizeof(pcb_file.header)); - auto offset = sizeof(pcb_file.header); - try - { - parseBlockEntry(data + offset, pcb_file.entries, offset, groupCounts[filename], *bgParts); - } - catch(std::exception& e) - { - std::cout << filename << " " << e.what() << "\n"; + total_indices += entry.header.num_indices; + /* + const auto& translationVec = pBgParts->header.translation; + const auto& rotationVec = pBgParts->header.rotation; + const auto& scaleVec = pBgParts->header.scale; + + auto xrot = matrix4::rotateX(rotationVec.x); + auto yrot = matrix4::rotateY(rotationVec.y); + auto zrot = matrix4::rotateZ(rotationVec.z); + */ + for( auto &vertex_list : entry.data.vertices ) + { + vec3 v; + v.x = vertex_list.x; + v.y = vertex_list.y; + v.z = vertex_list.z; + vertices.push_back( v ); + } + + 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 ) ); + + for( const auto &link : entry.data.vertices_i16 ) + { + vec3 v(float( link.x ) / 0xFFFF, float( link.y ) / 0xFFFF, float( link.z ) / 0xFFFF); + + float x = float( link.x ); + float y = float( link.y ); + float z = float( link.z ); + v.x = ( x / 0xFFFF ) * x_base + entry.header.x; + v.y = ( y / 0xFFFF ) * y_base + entry.header.y; + v.z = ( z / 0xFFFF ) * z_base + entry.header.z; + vertices.push_back( v ); + } + + + for( const auto &index : entry.data.indices ) + { + indices.push_back( int( index.index[0] ) + max_index ); + indices.push_back( int( index.index[1] ) + max_index ); + indices.push_back( int( index.index[2] ) + max_index ); + //std::cout << std::to_string( index.unknown[0] )<< " " << std::to_string( index.unknown[1] )<< " " << std::to_string( index.unknown[2]) << std::endl; + } + max_index = vertices.size(); } + //toFile("test.obj", vertices, indices); + //break; } } } + toFile("test.obj", vertices, indices); + std::cout << "vertices " << vertices.size() << " indices " << indices.size() / 3 << " expected indices " << vertices.size() << " total " << total_indices << "\n"; return 0; -} - -/* - for( uint16_t i = 0; i <= pcb_file.header.num_entries; i++ ) - { - PCB_BLOCK_ENTRY block_entry; - memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) ); - offset += sizeof( block_entry.header ); - - uint16_t block_size = sizeof( block_entry.header ) + - block_entry.header.num_vertices * 3 * 4 + - block_entry.header.num_v16 * 6 + - block_entry.header.num_indices * 6; - - if( block_entry.header.num_vertices != 0 ) - { - block_entry.data.vertices.resize( block_entry.header.num_vertices ); - - int32_t size_vertexbuffer = block_entry.header.num_vertices * 3; - memcpy( &block_entry.data.vertices[0], data + offset, size_vertexbuffer * 4 ); - offset += size_vertexbuffer * 4; - } - if( block_entry.header.num_v16 != 0 ) - { - block_entry.data.vertices_i16.resize( block_entry.header.num_v16 ); - int32_t size_unknownbuffer = block_entry.header.num_v16 * 6; - memcpy( &block_entry.data.vertices_i16[0], data + offset, size_unknownbuffer ); - offset += block_entry.header.num_v16 * 6; - } - if( block_entry.header.num_indices != 0 ) - { - block_entry.data.indices.resize( block_entry.header.num_indices ); - int32_t size_indexbuffer = block_entry.header.num_indices * 6; - memcpy( &block_entry.data.indices[0], data + offset, size_indexbuffer ); - offset += size_indexbuffer; - } - - // blocks always align to 16 bytes + 8 bytes padding till the next block - int rest = ( offset % 16 ); - if( rest > 0 ) - { - rest = 0x10 - rest; - } - offset += rest ; - - - pcb_file.entries.push_back( block_entry ); - } - - FILE* fp_out1 = fopen( std::string( filename + ".plain" ).c_str(), "w" ); - fprintf( fp_out1, ""); - fclose( fp_out1 ); - - FILE* fp_out = fopen( std::string( filename + ".plain" ).c_str(), "w+" ); - - fprintf( fp_out, "HEADER: num_entries: %i, total_indices: %i, unknown_1: %i\n\n", pcb_file.header.num_entries, pcb_file.header.total_indices, pcb_file.header.unknown_1 ); - - int block_cnt = 0; - for( auto& entry : pcb_file.entries ) - { - - fprintf( fp_out, "BLOCKHEADER_%i: type: %i, group_size: %i\n ", - block_cnt, entry.header.type, entry.header.group_size ); - fprintf( fp_out, "\tAABB: x: %f, y: %f, z: %f\n ", - entry.header.x, entry.header.y, entry.header.z ); - fprintf( fp_out, "\t\t x1: %f, y1: %f, z1: %f\n ", - entry.header.x1, entry.header.y1, entry.header.z1 ); - fprintf( fp_out, "\tnum_v16: %i, num_indices: %i, num_vertices: %i\n\n", - entry.header.num_v16, entry.header.num_indices, entry.header.num_vertices ); - - fprintf( fp_out, "Vertices: \n"); - for( auto& entry1 : entry.data.vertices ) - { - fprintf( fp_out, "\t %f, %f, %f \n", - entry1.x, entry1.y, entry1.z ); - } - - 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 ) ); - - fprintf( fp_out, "Vertices I16: \n" ); - for( auto& entry1 : entry.data.vertices_i16 ) - { - uint16_t var1 = entry1.x; - uint16_t var2 = entry1.y; - uint16_t var3 = entry1.z; - float x = ( var1 ); - float y = ( var2 ); - float z = ( var3 ); - fprintf( fp_out, "\t%f, ", (x / 0xFFFF) * x_base + entry.header.x ); - fprintf( fp_out, "%f, ", (y / 0xFFFF) * y_base + entry.header.y ); - fprintf( fp_out, "%f ", (z / 0xFFFF) * z_base + entry.header.z ); - fprintf( fp_out, "\n"); - - } - - - - - fprintf( fp_out, "Indices: \n" ); - for( auto& entry1 : entry.data.indices ) - { - fprintf( fp_out, "\t %i, %i, %i - %x,%x,%x \n", - entry1.index[0], entry1.index[1], entry1.index[2], entry1.unknown[0], entry1.unknown[1], entry1.unknown[2] ); - } - fprintf( fp_out, "\n" ); - } - - fclose( fp_out ); -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/tools/pcb_reader/matrix4.h b/src/tools/pcb_reader/matrix4.h new file mode 100644 index 00000000..c19808e2 --- /dev/null +++ b/src/tools/pcb_reader/matrix4.h @@ -0,0 +1,86 @@ +#ifndef _MATRIX4_H +#define _MATRIX4_H + +#include + +// https://github.com/jpd002/Play--Framework/tree/master/include/math +struct matrix4 +{ + // 4x4 + float grid[16]; + matrix4() + { + memset(&grid[0], 0, sizeof(grid)); + } + + float operator()(int row, int col) const + { + return grid[(row * 4) + col]; + } + + float& operator()(int row, int col) + { + return grid[(row * 4) + col]; + } + static matrix4 rotateX(float angle) + { + matrix4 ret = matrix4(); + ret(0, 0) = 1.000000000f; + ret(1, 1) = cos(angle); + ret(1, 2) = -sin(angle); + ret(2, 1) = sin(angle); + ret(2, 2) = cos(angle); + ret(3, 3) = 1.000000000f; + return ret; + } + + static matrix4 rotateY(float angle) + { + matrix4 ret = matrix4(); + ret(0, 0) = cos(angle); + ret(0, 2) = sin(angle); + ret(1, 1) = 1.000000000f; + ret(2, 0) = -sin(angle); + ret(2, 2) = cos(angle); + ret(3, 3) = 1.000000000f; + return ret; + } + + static matrix4 rotateZ(float angle) + { + matrix4 ret = matrix4(); + ret(0, 0) = cos(angle); + ret(0, 1) = -sin(angle); + ret(1, 0) = sin(angle); + ret(1, 1) = cos(angle); + ret(2, 2) = 1.000000000f; + ret(3, 3) = 1.000000000f; + return ret; + } + + static matrix4 scale(float x, float y, float z) + { + matrix4 ret = matrix4(); + ret(0, 0) = x; + ret(1, 1) = y; + ret(2, 2) = z; + ret(3, 3) = 1; + + return ret; + } + + static matrix4 translate(float x, float y, float z) + { + matrix4 ret = matrix4(); + ret(0, 0) = 1; + ret(1, 1) = 1; + ret(2, 2) = 1; + ret(3, 3) = 1; + + ret(3, 0) = x; + ret(3, 1) = y; + ret(3, 2) = z; + return ret; + } +}; +#endif \ No newline at end of file diff --git a/src/tools/pcb_reader/pcb.h b/src/tools/pcb_reader/pcb.h index 0139c431..165d7f7e 100644 --- a/src/tools/pcb_reader/pcb.h +++ b/src/tools/pcb_reader/pcb.h @@ -88,5 +88,4 @@ struct PCB_LIST_FILE PCB_LIST_BASE_ENTRY entry; std::vector entries; }; - #endif \ No newline at end of file diff --git a/src/tools/pcb_reader/vec3.h b/src/tools/pcb_reader/vec3.h new file mode 100644 index 00000000..a8fdfbd1 --- /dev/null +++ b/src/tools/pcb_reader/vec3.h @@ -0,0 +1,31 @@ +#ifndef _VEC3_H +#define _VEC3_H + +#include +#include "matrix4.h" + +struct vec3 +{ + float x, y, z; + vec3() + { + x = 0.0f; + y = 0.0f; + z = 0.0f; + } + vec3(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + }; +}; +static vec3 operator *(const vec3& lhs, const matrix4& rhs) +{ + vec3 ret; + ret.x = rhs(0, 0) * lhs.x + rhs(0, 1) * lhs.y + rhs(0, 2) * lhs.z; + ret.y = rhs(1, 0) * lhs.x + rhs(1, 1) * lhs.y + rhs(1, 2) * lhs.z; + ret.z = rhs(2, 0) * lhs.x + rhs(2, 1) * lhs.y + rhs(2, 2) * lhs.z; + return ret; +}; +#endif \ No newline at end of file