2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-06-28 07:11:52 +00:00

ObjLoading/ObjWriting: Initial skeleton for loading and writing obj files

This commit is contained in:
Jan
2019-12-29 16:40:03 +01:00
parent a0d4e87b8e
commit af55c202cf
39 changed files with 689 additions and 2 deletions

View File

@ -0,0 +1,16 @@
#include "IPakLoadException.h"
IPakLoadException::IPakLoadException(std::string message)
{
m_message = std::move(message);
}
const std::string& IPakLoadException::DetailedMessage() const
{
return m_message;
}
char const* IPakLoadException::what() const
{
return "There was an error when trying to load an ipak file.";
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <exception>
#include <string>
class IPakLoadException final : public std::exception
{
std::string m_message;
public:
explicit IPakLoadException(std::string message);
const std::string& DetailedMessage() const;
char const* what() const override;
};

View File

@ -0,0 +1,122 @@
#include "IPak.h"
#include "zlib.h"
#include "Exception/IPakLoadException.h"
#include <sstream>
const uint32_t IPak::MAGIC = 'IPAK';
const uint32_t IPak::VERSION = 0x50000;
uint32_t IPak::R_HashString(const char* str, uint32_t hash)
{
for (const char* pos = str; *pos; pos++)
{
hash = 33 * hash ^ (*pos | 0x20);
}
return hash;
}
IPak::IPak(FileAPI::IFile* file)
{
m_file = file;
m_initialized = false;
m_index_section = nullptr;
m_data_section = nullptr;
}
IPak::~IPak()
{
delete m_index_section;
m_index_section = nullptr;
delete m_data_section;
m_data_section = nullptr;
}
void IPak::ReadSection()
{
IPakSection section{};
if (m_file->Read(&section, sizeof section, 1) != sizeof section)
throw IPakLoadException("Unexpected eof when trying to load section.");
switch (section.type)
{
case 1:
m_index_section = new IPakSection(section);
break;
case 2:
m_data_section = new IPakSection(section);
break;
default:
break;
}
}
void IPak::ReadHeader()
{
IPakHeader header{};
if (m_file->Read(&header, sizeof header, 1) != sizeof header)
throw IPakLoadException("Unexpected eof when trying to load header.");
if (header.magic != MAGIC)
{
std::ostringstream oss;
oss << "Invalid magic '0x" << std::hex << header.magic << "'.";
throw IPakLoadException(oss.str());
}
if(header.version != VERSION)
{
std::ostringstream oss;
oss << "Unsupported version '" << header.version << "'.";
throw IPakLoadException(oss.str());
}
for(unsigned section = 0; section < header.sectionCount; section++)
{
ReadSection();
}
if(m_index_section == nullptr)
{
throw IPakLoadException("IPak does not contain an index section.");
}
if(m_data_section == nullptr)
{
throw IPakLoadException("IPak does not contain a data section.");
}
}
void IPak::Initialize()
{
if (m_initialized)
return;
ReadHeader();
m_initialized = true;
}
FileAPI::IFile* IPak::GetEntryData(IPakHash nameHash, IPakHash dataHash)
{
// TODO
return nullptr;
}
IPakHash IPak::HashString(const std::string& str)
{
return R_HashString(str.c_str(), 0);
}
IPakHash IPak::HashData(const void* data, const size_t dataSize)
{
return crc32(0, static_cast<const Bytef*>(data), dataSize);
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "Utils/FileAPI.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include "ObjContainer/ObjContainerReferenceable.h"
#include <vector>
class IPak final : public ObjContainerReferenceable
{
static const uint32_t MAGIC;
static const uint32_t VERSION;
FileAPI::IFile* m_file;
bool m_initialized;
IPakSection* m_index_section;
IPakSection* m_data_section;
std::vector<IPakIndexEntry> m_index_entries;
static uint32_t R_HashString(const char* str, uint32_t hash);
void ReadSection();
void ReadHeader();
public:
explicit IPak(FileAPI::IFile* file);
~IPak();
void Initialize();
FileAPI::IFile* GetEntryData(IPakHash nameHash, IPakHash dataHash);
static IPakHash HashString(const std::string& str);
static IPakHash HashData(const void* data, size_t dataSize);
};

View File

View File

View File

@ -0,0 +1,52 @@
#include "ObjContainerRegistry.h"
#include <cassert>
ObjContainerRegistry g_ObjContainerRegistry;
IObjContainer* ObjContainerRegistry::GetContainerByName(const std::string& name)
{
for (auto* container : m_containers)
{
if (container->GetName() == name)
{
return container;
}
}
return nullptr;
}
void ObjContainerRegistry::AddContainer(IObjContainer* container)
{
assert(dynamic_cast<ObjContainerReferenceable*>(container) == nullptr);
m_containers.push_back(container);
}
void ObjContainerRegistry::AddContainerWithReference(ObjContainerReferenceable* container, Zone* referencer)
{
container->AddReference(referencer);
m_containers.push_back(container);
}
void ObjContainerRegistry::RemoveContainerReferences(Zone* referencer)
{
auto iContainer = m_containers.begin();
while (iContainer != m_containers.end())
{
auto* container = *iContainer;
if (auto* referenceableContainer = dynamic_cast<ObjContainerReferenceable*>(container))
{
if (referenceableContainer->RemoveReference(referencer) && !referenceableContainer->IsReferenced())
{
delete container;
iContainer = m_containers.erase(iContainer);
continue;
}
}
++iContainer;
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "ObjContainer/IObjContainer.h"
#include "ObjContainer/ObjContainerReferenceable.h"
#include "Zone/Zone.h"
#include <string>
#include <vector>
class ObjContainerRegistry
{
std::vector<IObjContainer*> m_containers;
public:
void AddContainer(IObjContainer* container);
void AddContainerWithReference(ObjContainerReferenceable* container, Zone* referencer);
void RemoveContainerReferences(Zone* referencer);
IObjContainer* GetContainerByName(const std::string& name);
};
extern ObjContainerRegistry g_ObjContainerRegistry;