mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-29 07:37:45 +00:00
added list.pcb file mapping
- added LGB parser (all credit for LGB to contributor<https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/>, lgb.h is simply their work ported to c++) - todo: correct object placement
This commit is contained in:
parent
09391691b0
commit
04c53a9181
3 changed files with 395 additions and 71 deletions
267
src/tools/pcb_reader/lgb.h
Normal file
267
src/tools/pcb_reader/lgb.h
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
#ifndef _LGB_H
|
||||||
|
#define _LGB_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
|
// all credit to
|
||||||
|
// https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
|
||||||
|
// this is simply their work ported to c++ since we dont c#
|
||||||
|
struct LGB_FILE;
|
||||||
|
struct LGB_FILE_HEADER;
|
||||||
|
struct LGB_GROUP;
|
||||||
|
struct LGB_GROUP_HEADER;
|
||||||
|
|
||||||
|
struct vec3
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LgbEntryType : uint32_t
|
||||||
|
{
|
||||||
|
BgParts = 1,
|
||||||
|
Light = 3,
|
||||||
|
Vfx = 4,
|
||||||
|
PositionMarker = 5,
|
||||||
|
Gimmick = 6,
|
||||||
|
SharedGroup6 = 6,// secondary variable is set to 2
|
||||||
|
Sound = 7,
|
||||||
|
EventNpc = 8,
|
||||||
|
BattleNpc = 9,
|
||||||
|
Aetheryte = 12,
|
||||||
|
EnvSpace = 13,
|
||||||
|
Gathering = 14,
|
||||||
|
SharedGroup15 = 15,// secondary variable is set to 13
|
||||||
|
Treasure = 16,
|
||||||
|
Weapon = 39,
|
||||||
|
PopRange = 40,
|
||||||
|
ExitRange = 41,
|
||||||
|
MapRange = 43,
|
||||||
|
NaviMeshRange = 44,
|
||||||
|
EventObject = 45,
|
||||||
|
EnvLocation = 47,
|
||||||
|
EventRange = 49,
|
||||||
|
QuestMarker = 51,
|
||||||
|
CollisionBox = 57,
|
||||||
|
DoorRange = 58,
|
||||||
|
LineVfx = 59,
|
||||||
|
ClientPath = 65,
|
||||||
|
ServerPath = 66,
|
||||||
|
GimmickRange = 67,
|
||||||
|
TargetMarker = 68,
|
||||||
|
ChairMarker = 69,
|
||||||
|
ClickableRange = 70,
|
||||||
|
PrefetchRange = 71,
|
||||||
|
FateRange = 72,
|
||||||
|
SphereCastRange = 75,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_BGPARTS_HEADER
|
||||||
|
{
|
||||||
|
LgbEntryType type;
|
||||||
|
uint32_t unknown2;
|
||||||
|
uint32_t nameOffset;
|
||||||
|
vec3 translation;
|
||||||
|
vec3 rotation;
|
||||||
|
vec3 scale;
|
||||||
|
uint32_t modelFileOffset;
|
||||||
|
uint32_t collisionFileOffset;
|
||||||
|
uint32_t unknown4;
|
||||||
|
uint32_t unknown5;
|
||||||
|
uint32_t unknown6;
|
||||||
|
uint32_t unknown7;
|
||||||
|
uint32_t unknown8;
|
||||||
|
uint32_t unknown9;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LGB_MODEL_ENTRY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
char* m_buf;
|
||||||
|
uint32_t m_offset;
|
||||||
|
|
||||||
|
LGB_MODEL_ENTRY()
|
||||||
|
{
|
||||||
|
m_buf = nullptr;
|
||||||
|
m_offset = 0;
|
||||||
|
};
|
||||||
|
LGB_MODEL_ENTRY(char* buf, uint32_t offset)
|
||||||
|
{
|
||||||
|
m_buf = buf;
|
||||||
|
m_offset = offset;
|
||||||
|
};
|
||||||
|
virtual ~LGB_MODEL_ENTRY(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
class LGB_BGPARTS_ENTRY : public LGB_MODEL_ENTRY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LGB_BGPARTS_HEADER header;
|
||||||
|
std::string name;
|
||||||
|
std::string modelFileName;
|
||||||
|
std::string collisionFileName;
|
||||||
|
LGB_BGPARTS_ENTRY(){};
|
||||||
|
LGB_BGPARTS_ENTRY(char* buf, uint32_t offset)
|
||||||
|
{
|
||||||
|
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>(buf + offset);
|
||||||
|
name = std::string(buf + offset + header.nameOffset);
|
||||||
|
modelFileName = std::string(buf + offset + header.modelFileOffset);
|
||||||
|
collisionFileName = std::string(buf + offset + header.collisionFileOffset);
|
||||||
|
//std::cout << "BGPARTS_ENTRY " << name << "\n";
|
||||||
|
//std::cout << " " << modelFileName << "\n";
|
||||||
|
//std::cout << " " << collisionFileName << "\n";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_GIMMICK_HEADER
|
||||||
|
{
|
||||||
|
LgbEntryType type;
|
||||||
|
uint32_t unknown;
|
||||||
|
uint32_t nameOffset;
|
||||||
|
vec3 translation;
|
||||||
|
vec3 rotation;
|
||||||
|
vec3 scale;
|
||||||
|
uint32_t gimmickFileOffset;
|
||||||
|
char unknownBytes[100];
|
||||||
|
};
|
||||||
|
|
||||||
|
class LGB_GIMMICK_ENTRY : public LGB_MODEL_ENTRY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LGB_GIMMICK_HEADER header;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
LGB_GIMMICK_ENTRY(char* buf, uint32_t offset)
|
||||||
|
{
|
||||||
|
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>(buf + offset);
|
||||||
|
name = std::string(buf + offset + header.nameOffset);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_GROUP_HEADER
|
||||||
|
{
|
||||||
|
uint32_t unknown;
|
||||||
|
int32_t groupNameOffset;
|
||||||
|
int32_t entriesOffset;
|
||||||
|
int32_t entryCount;
|
||||||
|
uint32_t unknown2;
|
||||||
|
uint32_t unknown3;
|
||||||
|
uint32_t unknown4;
|
||||||
|
uint32_t unknown5;
|
||||||
|
uint32_t unknown6;
|
||||||
|
uint32_t unknown7;
|
||||||
|
uint32_t unknown8;
|
||||||
|
uint32_t unknown9;
|
||||||
|
uint32_t unknown10;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_GROUP
|
||||||
|
{
|
||||||
|
LGB_FILE* parent;
|
||||||
|
LGB_GROUP_HEADER header;
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::shared_ptr<LGB_MODEL_ENTRY>> entries;
|
||||||
|
|
||||||
|
LGB_GROUP(char* buf, LGB_FILE* parentStruct, uint32_t offset)
|
||||||
|
{
|
||||||
|
parent = parentStruct;
|
||||||
|
header = *reinterpret_cast<LGB_GROUP_HEADER*>(buf + offset);
|
||||||
|
name = std::string(buf + offset + header.groupNameOffset);
|
||||||
|
entries.resize(header.entryCount);
|
||||||
|
//std::cout << name << std::endl;
|
||||||
|
auto entriesOffset = offset + header.entriesOffset;
|
||||||
|
for( auto i = 0; i < header.entryCount; ++i)
|
||||||
|
{
|
||||||
|
auto entryOffset = entriesOffset + *reinterpret_cast<int32_t*>(buf + (entriesOffset + i * 4));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto type = *reinterpret_cast<LgbEntryType*>(buf + entryOffset);
|
||||||
|
LGB_MODEL_ENTRY* entry;
|
||||||
|
if (type == LgbEntryType::BgParts)
|
||||||
|
{
|
||||||
|
entries[i] = std::make_shared<LGB_BGPARTS_ENTRY>(buf, entryOffset);
|
||||||
|
}
|
||||||
|
else if (type == LgbEntryType::Gimmick)
|
||||||
|
{
|
||||||
|
entries[i] = std::make_shared<LGB_GIMMICK_ENTRY>(buf, entryOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_FILE_HEADER
|
||||||
|
{
|
||||||
|
char magic[4]; // LGB 1
|
||||||
|
uint32_t fileSize;
|
||||||
|
uint32_t unknown;
|
||||||
|
char magic2[4]; // LGP1
|
||||||
|
uint32_t unknown2;
|
||||||
|
uint32_t unknown3;
|
||||||
|
uint32_t unknown4;
|
||||||
|
uint32_t unknown5;
|
||||||
|
int32_t groupCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_FILE
|
||||||
|
{
|
||||||
|
LGB_FILE_HEADER header;
|
||||||
|
std::vector<LGB_GROUP> groups;
|
||||||
|
|
||||||
|
LGB_FILE(char* buf)
|
||||||
|
{
|
||||||
|
header = *reinterpret_cast<LGB_FILE_HEADER*>(buf);
|
||||||
|
if (strncmp(&header.magic[0], "LGB1", 4) != 0 || strncmp(&header.magic2[0], "LGP1", 4) != 0)
|
||||||
|
throw std::exception("Invalid LGB file!");
|
||||||
|
|
||||||
|
//groups.resize(header.groupCount);
|
||||||
|
|
||||||
|
auto baseOffset = sizeof(header);
|
||||||
|
for(auto i = 0; i < header.groupCount; ++i)
|
||||||
|
{
|
||||||
|
auto groupOffset = baseOffset + *reinterpret_cast<int32_t*>(buf + (baseOffset + i * 4));
|
||||||
|
auto group = LGB_GROUP(buf, this, groupOffset);
|
||||||
|
groups.push_back(group);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, LGB_FILE> getLgbFiles(const std::string& dir)
|
||||||
|
{
|
||||||
|
namespace fs = std::experimental::filesystem;
|
||||||
|
std::map<std::string, LGB_FILE> fileMap;
|
||||||
|
for (const auto& path : fs::recursive_directory_iterator(dir))
|
||||||
|
{
|
||||||
|
if (path.path().extension() == ".lgb")
|
||||||
|
{
|
||||||
|
auto strPath = path.path().string();
|
||||||
|
auto f = fopen(strPath.c_str(), "rb");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
auto size = ftell(f);
|
||||||
|
std::vector<char> bytes(size);
|
||||||
|
rewind(f);
|
||||||
|
fread(bytes.data(), 1, size, f);
|
||||||
|
fclose(f);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LGB_FILE lgbFile(bytes.data());
|
||||||
|
fileMap.insert(std::make_pair(strPath, lgbFile));
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Unable to load " << strPath << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileMap;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,17 +1,41 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#include <string.h>
|
#include <string>
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
#include "pcb.h"
|
#include "pcb.h"
|
||||||
|
#include "lgb.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
namespace fs = std::experimental::filesystem;
|
||||||
|
|
||||||
int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff )
|
std::vector<std::string> loadDir(const std::string& dir)
|
||||||
|
{
|
||||||
|
std::vector<std::string> files;
|
||||||
|
|
||||||
|
auto fsDir = fs::current_path().append(fs::path(dir));
|
||||||
|
std::cout << fsDir.string() << "\n";
|
||||||
|
if (fs::exists(fsDir))
|
||||||
|
{
|
||||||
|
for (const auto& entry : fs::directory_iterator(fsDir))
|
||||||
|
{
|
||||||
|
auto filename = entry.path().filename();
|
||||||
|
if (filename.string().find("~") == -1)
|
||||||
|
files.push_back(entry.path().string());
|
||||||
|
if (filename.string().find("list") != std::string::npos)
|
||||||
|
std::cout << filename.string() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff, uint32_t& groupCount, LGB_BGPARTS_ENTRY& bgParts )
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
bool isgroup = true;
|
bool isgroup = true;
|
||||||
while( isgroup )
|
while( isgroup )
|
||||||
{
|
{
|
||||||
|
groupCount++;
|
||||||
PCB_BLOCK_ENTRY block_entry;
|
PCB_BLOCK_ENTRY block_entry;
|
||||||
memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) );
|
memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) );
|
||||||
isgroup = block_entry.header.type == 0x30 ? true : false;
|
isgroup = block_entry.header.type == 0x30 ? true : false;
|
||||||
|
@ -20,14 +44,13 @@ int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff
|
||||||
|
|
||||||
if( isgroup )
|
if( isgroup )
|
||||||
{
|
{
|
||||||
parseBlockEntry( data + offset + 0x30, entries, gOff + offset );
|
parseBlockEntry( data + offset + 0x30, entries, gOff + offset, groupCount, bgParts );
|
||||||
offset += block_entry.header.group_size;
|
offset += block_entry.header.group_size;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf( "\tnum_v16: %i, num_indices: %i, num_vertices: %i\n\n",
|
//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 );
|
// block_entry.header.num_v16, block_entry.header.num_indices, block_entry.header.num_vertices );
|
||||||
int doffset = sizeof( block_entry.header ) + offset;
|
int doffset = sizeof( block_entry.header ) + offset;
|
||||||
uint16_t block_size = sizeof( block_entry.header ) +
|
uint16_t block_size = sizeof( block_entry.header ) +
|
||||||
block_entry.header.num_vertices * 3 * 4 +
|
block_entry.header.num_vertices * 3 * 4 +
|
||||||
|
@ -58,18 +81,18 @@ int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff
|
||||||
}
|
}
|
||||||
entries.push_back( block_entry );
|
entries.push_back( block_entry );
|
||||||
|
|
||||||
/* printf( "Vertices: \n" );
|
//printf( "Vertices: \n" );
|
||||||
for( auto& entry1 : block_entry.data.vertices )
|
for( auto& entry1 : block_entry.data.vertices )
|
||||||
{
|
{
|
||||||
printf( "\t %f, %f, %f \n",
|
// printf( "\t %f, %f, %f \n",
|
||||||
entry1.x, entry1.y, entry1.z );
|
// entry1.x, entry1.y, entry1.z );
|
||||||
}
|
}
|
||||||
|
|
||||||
float x_base = abs( float( block_entry.header.x1 - block_entry.header.x ) );
|
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 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 ) );
|
float z_base = abs( float( block_entry.header.z1 - block_entry.header.z ) );
|
||||||
|
|
||||||
printf( "Vertices I16: \n" );
|
//printf( "Vertices I16: \n" );
|
||||||
for( auto& entry1 : block_entry.data.vertices_i16 )
|
for( auto& entry1 : block_entry.data.vertices_i16 )
|
||||||
{
|
{
|
||||||
uint16_t var1 = entry1.x;
|
uint16_t var1 = entry1.x;
|
||||||
|
@ -78,12 +101,12 @@ int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff
|
||||||
float x = ( var1 );
|
float x = ( var1 );
|
||||||
float y = ( var2 );
|
float y = ( var2 );
|
||||||
float z = ( var3 );
|
float z = ( var3 );
|
||||||
printf( "\t%f, ", ( x / 0xFFFF ) * x_base + block_entry.header.x );
|
//printf( "\t%f, ", ( x / 0xFFFF ) * x_base + block_entry.header.x );
|
||||||
printf( "%f, ", ( y / 0xFFFF ) * y_base + block_entry.header.y );
|
//printf( "%f, ", ( y / 0xFFFF ) * y_base + block_entry.header.y );
|
||||||
printf( "%f ", ( z / 0xFFFF ) * z_base + block_entry.header.z );
|
//printf( "%f ", ( z / 0xFFFF ) * z_base + block_entry.header.z );
|
||||||
printf( "\n" );
|
//printf( "\n" );
|
||||||
|
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +119,37 @@ int main()
|
||||||
|
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
//r1f1_b1_dor00.pcb
|
//r1f1_b1_dor00.pcb
|
||||||
|
PCB_LIST_FILE listFile;
|
||||||
|
int groupsCount = 0;
|
||||||
|
//auto list = loadDir("bg/ffxiv/roc_r1/collision");
|
||||||
|
auto lgbFiles = getLgbFiles("bg/ffxiv/roc_r1/");
|
||||||
|
|
||||||
|
std::cout << "Loaded " << lgbFiles.size() << " LGB files" << std::endl;
|
||||||
|
|
||||||
|
uint64_t vertexCount = 0;
|
||||||
|
std::map<std::string, uint32_t> groupCounts;
|
||||||
|
for (const auto& pair : lgbFiles)
|
||||||
|
{
|
||||||
|
for (const auto& group : pair.second.groups)
|
||||||
|
{
|
||||||
|
uint32_t bgPartsCount = 0;
|
||||||
|
std::cout << group.name << "\n";
|
||||||
|
for (auto entry : group.entries)
|
||||||
|
{
|
||||||
|
if (dynamic_cast<LGB_BGPARTS_ENTRY*>(entry.get()))
|
||||||
|
bgPartsCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto entry : group.entries)
|
||||||
|
{
|
||||||
|
auto bgParts = dynamic_cast<LGB_BGPARTS_ENTRY*>(entry.get());
|
||||||
|
if (!bgParts)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto& filename = bgParts->collisionFileName;
|
||||||
|
std::cout << filename << std::endl;
|
||||||
//std::string filename( "f1h0_s_rof0003.pcb" );
|
//std::string filename( "f1h0_s_rof0003.pcb" );
|
||||||
std::string filename( "tr0924.pcb" );
|
//std::string filename("tr0924.pcb");
|
||||||
FILE *fp = nullptr;
|
FILE *fp = nullptr;
|
||||||
fp = fopen(filename.c_str(), "rb");
|
fp = fopen(filename.c_str(), "rb");
|
||||||
if (fp == nullptr)
|
if (fp == nullptr)
|
||||||
|
@ -115,37 +166,22 @@ int main()
|
||||||
|
|
||||||
PCB_FILE pcb_file;
|
PCB_FILE pcb_file;
|
||||||
memcpy(&pcb_file.header, data, sizeof(pcb_file.header));
|
memcpy(&pcb_file.header, data, sizeof(pcb_file.header));
|
||||||
offset += sizeof( pcb_file.header );
|
auto offset = sizeof(pcb_file.header);
|
||||||
|
try
|
||||||
|
|
||||||
|
|
||||||
std::vector<PCB_BLOCK_ENTRY> entries;
|
|
||||||
|
|
||||||
bool isgroup = true;
|
|
||||||
while( isgroup )
|
|
||||||
{
|
{
|
||||||
PCB_BLOCK_ENTRY block_entry;
|
parseBlockEntry(data + offset, pcb_file.entries, offset, groupCounts[filename], *bgParts);
|
||||||
memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) );
|
|
||||||
isgroup = block_entry.header.type == 0x30 ? true : false;
|
|
||||||
|
|
||||||
//printf( "BLOCKHEADER_%X: type: %i, group_size: %i\n", offset, block_entry.header.type, block_entry.header.group_size );
|
|
||||||
|
|
||||||
if( isgroup )
|
|
||||||
{
|
|
||||||
std::vector<uint8_t> data_block( block_entry.header.group_size );
|
|
||||||
memcpy( &data_block[0], data + offset, block_entry.header.group_size );
|
|
||||||
parseBlockEntry( (char*)&data_block[0] + 0x30, entries, offset );
|
|
||||||
offset += block_entry.header.group_size;
|
|
||||||
}
|
}
|
||||||
else
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
parseBlockEntry( data + offset, entries, offset );
|
std::cout << filename << " " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
for( uint16_t i = 0; i <= pcb_file.header.num_entries; i++ )
|
for( uint16_t i = 0; i <= pcb_file.header.num_entries; i++ )
|
||||||
{
|
{
|
||||||
PCB_BLOCK_ENTRY block_entry;
|
PCB_BLOCK_ENTRY block_entry;
|
||||||
|
@ -253,6 +289,4 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fp_out );
|
fclose( fp_out );
|
||||||
|
*/
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef _PCB_H
|
||||||
|
#define _PCB_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -67,3 +70,23 @@ struct PCB_FILE
|
||||||
PCB_HEADER header;
|
PCB_HEADER header;
|
||||||
std::vector< PCB_BLOCK_ENTRY > entries;
|
std::vector< PCB_BLOCK_ENTRY > entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PCB_LIST_ENTRY
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
float x, y, z, x2, y2, z2, rot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PCB_LIST_BASE_ENTRY
|
||||||
|
{
|
||||||
|
float x, y, z, x2, y2, z2, rot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PCB_LIST_FILE
|
||||||
|
{
|
||||||
|
uint32_t count;
|
||||||
|
PCB_LIST_BASE_ENTRY entry;
|
||||||
|
std::vector<PCB_LIST_ENTRY> entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue