chore: add output implementations for gltf and glb

This commit is contained in:
Jan 2024-03-31 22:46:31 +02:00
parent 7a0930a208
commit c27f4ed544
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
7 changed files with 228 additions and 0 deletions

View File

@ -0,0 +1,20 @@
#pragma once
#include "Utils/FileUtils.h"
#include <cstdint>
namespace gltf
{
constexpr uint32_t GLTF_MAGIC = FileUtils::MakeMagic32('g', 'l', 'T', 'F');
constexpr uint32_t GLTF_VERSION = 2u;
constexpr uint32_t CHUNK_MAGIC_JSON = FileUtils::MakeMagic32('J', 'S', 'O', 'N');
constexpr uint32_t CHUNK_MAGIC_BIN = FileUtils::MakeMagic32('B', 'I', 'N', '\x00');
constexpr auto GLTF_LENGTH_OFFSET = 8u;
constexpr auto GLTF_JSON_CHUNK_LENGTH_OFFSET = 12u;
constexpr auto GLTF_JSON_CHUNK_DATA_OFFSET = 20u;
constexpr auto GLTF_DATA_URI_PREFIX = "data:application/octet-stream;base64,";
} // namespace gltf

View File

@ -19,6 +19,7 @@ function ObjWriting:link(links)
links:linkto(ZoneCommon)
links:linkto(minilzo)
links:linkto(minizip)
links:linkto(libtomcrypt)
end
function ObjWriting:use()
@ -55,5 +56,6 @@ function ObjWriting:project()
minilzo:include(includes)
minizip:include(includes)
json:include(includes)
libtomcrypt:include(includes)
end

View File

@ -0,0 +1,86 @@
#include "GltfBinOutput.h"
#include "Utils/Alignment.h"
#include "XModel/Gltf/GltfConstants.h"
#include <cstdint>
#include <nlohmann/json.hpp>
using namespace gltf;
BinOutput::BinOutput(std::ostream& stream)
: m_stream(stream)
{
}
void BinOutput::Write(const void* data, const size_t dataSize) const
{
m_stream.write(static_cast<const char*>(data), dataSize);
}
void BinOutput::AlignToFour(const char value) const
{
const auto offset = m_stream.tellp();
if (offset % 4 > 0)
{
const uint32_t alignmentValue = FileUtils::MakeMagic32(value, value, value, value);
Write(&alignmentValue, 4u - (offset % 4u));
}
}
std::optional<std::string> BinOutput::CreateBufferUri(const void* buffer, size_t bufferSize) const
{
return std::nullopt;
}
void BinOutput::EmitJson(const nlohmann::json& json) const
{
static constexpr uint32_t ZERO = 0u;
Write(&GLTF_MAGIC, sizeof(GLTF_MAGIC));
Write(&GLTF_VERSION, sizeof(GLTF_VERSION));
// File length will be filled later
Write(&ZERO, sizeof(ZERO));
// Chunk length will be filled after writing json
Write(&ZERO, sizeof(ZERO));
Write(&CHUNK_MAGIC_JSON, sizeof(CHUNK_MAGIC_JSON));
m_stream << json;
AlignToFour(' ');
const auto offsetAfterData = m_stream.tellp();
const auto jsonDataLength = static_cast<uint32_t>(static_cast<unsigned>(offsetAfterData) - GLTF_JSON_CHUNK_DATA_OFFSET);
// Fill chunk length now
m_stream.seekp(GLTF_JSON_CHUNK_LENGTH_OFFSET, std::ios::beg);
Write(&jsonDataLength, sizeof(jsonDataLength));
// Return to previous pos
m_stream.seekp(offsetAfterData, std::ios::beg);
}
void BinOutput::EmitBuffer(const void* buffer, const size_t bufferSize) const
{
const auto chunkLength = utils::Align<uint32_t>(bufferSize, 4u);
Write(&chunkLength, sizeof(chunkLength));
Write(&CHUNK_MAGIC_BIN, sizeof(CHUNK_MAGIC_BIN));
Write(buffer, bufferSize);
AlignToFour('\0');
}
void BinOutput::Finalize() const
{
const auto fileEndOffset = m_stream.tellp();
const auto fileSize = static_cast<uint32_t>(fileEndOffset);
// Fill chunk length now
m_stream.seekp(GLTF_LENGTH_OFFSET, std::ios::beg);
Write(&fileSize, sizeof(fileSize));
// Return to file end
m_stream.seekp(fileEndOffset, std::ios::beg);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "GltfOutput.h"
#include <ostream>
namespace gltf
{
class BinOutput final : public Output
{
public:
explicit BinOutput(std::ostream& stream);
std::optional<std::string> CreateBufferUri(const void* buffer, size_t bufferSize) const override;
void EmitJson(const nlohmann::json& json) const override;
void EmitBuffer(const void* buffer, size_t bufferSize) const override;
void Finalize() const override;
private:
void Write(const void* data, size_t dataSize) const;
void AlignToFour(char value) const;
std::ostream& m_stream;
};
} // namespace gltf

View File

@ -0,0 +1,25 @@
#pragma once
#include <nlohmann/json_fwd.hpp>
#include <optional>
#include <string>
namespace gltf
{
class Output
{
protected:
Output() = default;
virtual ~Output() = default;
Output(const Output& other) = default;
Output(Output&& other) noexcept = default;
Output& operator=(const Output& other) = default;
Output& operator=(Output&& other) noexcept = default;
public:
virtual std::optional<std::string> CreateBufferUri(const void* buffer, size_t bufferSize) const = 0;
virtual void EmitJson(const nlohmann::json& json) const = 0;
virtual void EmitBuffer(const void* buffer, size_t bufferSize) const = 0;
virtual void Finalize() const = 0;
};
} // namespace gltf

View File

@ -0,0 +1,48 @@
#include "GltfTextOutput.h"
#include "Utils/Alignment.h"
#include "XModel/Gltf/GltfConstants.h"
#include <iomanip>
#include <nlohmann/json.hpp>
#include <tomcrypt.h>
using namespace gltf;
TextOutput::TextOutput(std::ostream& stream)
: m_stream(stream)
{
}
std::optional<std::string> TextOutput::CreateBufferUri(const void* buffer, const size_t bufferSize) const
{
static constexpr auto URI_PREFIX_LENGTH = std::char_traits<char>::length(GLTF_DATA_URI_PREFIX);
const auto base64Length = utils::Align(4u * (bufferSize / 3u), 4u);
const auto base64BufferSize = URI_PREFIX_LENGTH + base64Length;
std::string output(base64BufferSize, '\0');
std::memcpy(output.data(), &GLTF_DATA_URI_PREFIX, URI_PREFIX_LENGTH);
unsigned long outLength = base64Length;
base64_encode(static_cast<const unsigned char*>(buffer), bufferSize, &output[URI_PREFIX_LENGTH], &outLength);
assert(outLength == base64Length);
return output;
}
void TextOutput::EmitJson(const nlohmann::json& json) const
{
m_stream << std::setw(4) << json;
}
void TextOutput::EmitBuffer(const void* buffer, const size_t bufferSize) const
{
// Nothing to do
}
void TextOutput::Finalize() const
{
// Nothing to do
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "GltfOutput.h"
#include <ostream>
namespace gltf
{
class TextOutput final : public Output
{
public:
explicit TextOutput(std::ostream& stream);
std::optional<std::string> CreateBufferUri(const void* buffer, size_t bufferSize) const override;
void EmitJson(const nlohmann::json& json) const override;
void EmitBuffer(const void* buffer, size_t bufferSize) const override;
void Finalize() const override;
private:
std::ostream& m_stream;
};
} // namespace gltf