mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 07:42:54 +00:00
129 lines
3.2 KiB
C++
129 lines
3.2 KiB
C++
#include "GltfBinInput.h"
|
|
|
|
#include "XModel/Gltf/GltfConstants.h"
|
|
|
|
#include <exception>
|
|
#include <iostream>
|
|
#include <nlohmann/json.hpp>
|
|
|
|
using namespace gltf;
|
|
|
|
BinInput::BinInput()
|
|
: m_buffer_size(0u)
|
|
{
|
|
}
|
|
|
|
bool BinInput::GetEmbeddedBuffer(const void*& buffer, size_t& bufferSize) const
|
|
{
|
|
if (!m_buffer || !m_buffer_size)
|
|
return false;
|
|
|
|
buffer = m_buffer.get();
|
|
bufferSize = m_buffer_size;
|
|
|
|
return true;
|
|
}
|
|
|
|
const nlohmann::json& BinInput::GetJson() const
|
|
{
|
|
if (!m_json)
|
|
throw std::exception();
|
|
|
|
return *m_json;
|
|
}
|
|
|
|
bool BinInput::ReadGltfData(std::istream& stream)
|
|
{
|
|
uint32_t magic;
|
|
if (!Read(stream, &magic, sizeof(magic), "magic"))
|
|
return false;
|
|
|
|
if (magic != GLTF_MAGIC)
|
|
{
|
|
std::cerr << "Invalid magic when trying to read GLB\n";
|
|
return false;
|
|
}
|
|
|
|
uint32_t version;
|
|
if (!Read(stream, &version, sizeof(version), "version"))
|
|
return false;
|
|
|
|
if (version != GLTF_VERSION)
|
|
{
|
|
std::cerr << std::format("Unsupported version {} when trying to read GLB: Expected version {}\n", version, GLTF_VERSION);
|
|
return false;
|
|
}
|
|
|
|
uint32_t fileLength;
|
|
if (!Read(stream, &fileLength, sizeof(fileLength), "file length"))
|
|
return false;
|
|
|
|
while (true)
|
|
{
|
|
uint32_t chunkLength;
|
|
uint32_t chunkMagic;
|
|
if (!Read(stream, &chunkLength, sizeof(chunkLength), "chunk length", false))
|
|
break;
|
|
|
|
if (!Read(stream, &chunkMagic, sizeof(chunkMagic), "chunk magic"))
|
|
return false;
|
|
|
|
if (chunkMagic == CHUNK_MAGIC_JSON)
|
|
{
|
|
const auto jsonBuffer = std::make_unique<uint8_t[]>(chunkLength + 1);
|
|
if (!Read(stream, jsonBuffer.get(), chunkLength, "json"))
|
|
return false;
|
|
jsonBuffer[chunkLength] = 0u;
|
|
|
|
try
|
|
{
|
|
m_json = std::make_unique<nlohmann::json>(nlohmann::json::parse(jsonBuffer.get(), &jsonBuffer[chunkLength]));
|
|
}
|
|
catch (const nlohmann::json::exception& e)
|
|
{
|
|
std::cerr << std::format("Failed trying to parse JSON of GLB: {}\n", e.what());
|
|
return false;
|
|
}
|
|
}
|
|
else if (chunkMagic == CHUNK_MAGIC_BIN)
|
|
{
|
|
m_buffer = std::make_unique<uint8_t[]>(chunkLength);
|
|
m_buffer_size = chunkLength;
|
|
|
|
if (!Read(stream, m_buffer.get(), m_buffer_size, "bin buffer"))
|
|
return false;
|
|
}
|
|
else
|
|
Skip(stream, chunkLength);
|
|
|
|
if (chunkLength % 4u > 0)
|
|
Skip(stream, 4u - (chunkLength % 4u));
|
|
}
|
|
|
|
if (!m_json)
|
|
{
|
|
std::cerr << "Failed to load GLB due to missing JSON\n";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BinInput::Read(std::istream& stream, void* dest, const size_t dataSize, const char* readTypeName, const bool errorWhenFailed)
|
|
{
|
|
stream.read(static_cast<char*>(dest), dataSize);
|
|
if (stream.gcount() != dataSize)
|
|
{
|
|
if (errorWhenFailed)
|
|
std::cerr << std::format("Unexpected EOF while reading GLB {}\n", readTypeName);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void BinInput::Skip(std::istream& stream, const size_t skipLength)
|
|
{
|
|
stream.seekg(skipLength, std::ios::cur);
|
|
}
|