asset compression
This commit is contained in:
parent
b9b9ecb84c
commit
30a283c1b3
57 changed files with 13237 additions and 8 deletions
|
|
@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
*/
|
||||
|
||||
export module Crafter.Asset:Mesh;
|
||||
import :Compression;
|
||||
import Crafter.Math;
|
||||
import std;
|
||||
namespace fs = std::filesystem;
|
||||
|
|
@ -35,6 +36,44 @@ export namespace Crafter {
|
|||
Vector<float, 2, 0> uv;
|
||||
};
|
||||
|
||||
// GDeflate-compressed counterpart of MeshAsset<T>::Save output. Three
|
||||
// regions: [vertex, index, data]. dataCount==0 leaves the data region
|
||||
// empty (zero compressedSize/decompressedSize). dataStride records sizeof(T)
|
||||
// at compress time so consumers can validate.
|
||||
struct CompressedMeshAsset {
|
||||
std::uint32_t vertexCount = 0;
|
||||
std::uint32_t indexCount = 0;
|
||||
std::uint32_t dataCount = 0;
|
||||
std::uint32_t dataStride = 0;
|
||||
Compression::CompressedBlob blob;
|
||||
};
|
||||
|
||||
namespace MeshAssetFormat {
|
||||
inline constexpr char magic[4] = {'C', 'G', 'D', 'M'};
|
||||
inline constexpr std::uint32_t version = 1;
|
||||
}
|
||||
|
||||
inline CompressedMeshAsset LoadCompressedMesh(fs::path path) {
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
char magic[4];
|
||||
file.read(magic, 4);
|
||||
if (std::memcmp(magic, MeshAssetFormat::magic, 4) != 0) {
|
||||
throw std::runtime_error("LoadCompressedMesh: bad magic on " + path.string());
|
||||
}
|
||||
std::uint32_t version = 0;
|
||||
file.read(reinterpret_cast<char*>(&version), sizeof(version));
|
||||
if (version != MeshAssetFormat::version) {
|
||||
throw std::runtime_error("LoadCompressedMesh: unsupported version on " + path.string());
|
||||
}
|
||||
CompressedMeshAsset out;
|
||||
file.read(reinterpret_cast<char*>(&out.vertexCount), sizeof(out.vertexCount));
|
||||
file.read(reinterpret_cast<char*>(&out.indexCount), sizeof(out.indexCount));
|
||||
file.read(reinterpret_cast<char*>(&out.dataCount), sizeof(out.dataCount));
|
||||
file.read(reinterpret_cast<char*>(&out.dataStride), sizeof(out.dataStride));
|
||||
out.blob = Compression::ReadBlob(file);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct MeshAsset {
|
||||
std::vector<Vector<float, 3, 3>> vertexes;
|
||||
|
|
@ -57,6 +96,29 @@ export namespace Crafter {
|
|||
file.write(reinterpret_cast<char*>(datas.data()), dataCount * sizeof(T));
|
||||
}
|
||||
|
||||
void SaveCompressed(fs::path path) const {
|
||||
std::array<std::span<const std::byte>, 3> streams = {
|
||||
std::as_bytes(std::span(vertexes)),
|
||||
std::as_bytes(std::span(indexes)),
|
||||
std::as_bytes(std::span(datas)),
|
||||
};
|
||||
Compression::CompressedBlob blob = Compression::CompressStreams(streams);
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file.write(MeshAssetFormat::magic, 4);
|
||||
std::uint32_t version = MeshAssetFormat::version;
|
||||
std::uint32_t vc = static_cast<std::uint32_t>(vertexes.size());
|
||||
std::uint32_t ic = static_cast<std::uint32_t>(indexes.size());
|
||||
std::uint32_t dc = static_cast<std::uint32_t>(datas.size());
|
||||
std::uint32_t stride = static_cast<std::uint32_t>(sizeof(T));
|
||||
file.write(reinterpret_cast<const char*>(&version), sizeof(version));
|
||||
file.write(reinterpret_cast<const char*>(&vc), sizeof(vc));
|
||||
file.write(reinterpret_cast<const char*>(&ic), sizeof(ic));
|
||||
file.write(reinterpret_cast<const char*>(&dc), sizeof(dc));
|
||||
file.write(reinterpret_cast<const char*>(&stride), sizeof(stride));
|
||||
Compression::WriteBlob(file, blob);
|
||||
}
|
||||
|
||||
static MeshAsset<T> Load(fs::path path) {
|
||||
MeshAsset<T> mesh;
|
||||
|
||||
|
|
@ -196,6 +258,32 @@ export namespace Crafter {
|
|||
file.write(reinterpret_cast<char*>(vertexes.data()), vertexCount * sizeof(Vector<float, 3, 3>));
|
||||
file.write(reinterpret_cast<char*>(indexes.data()), indexCount * sizeof(std::uint32_t));
|
||||
}
|
||||
|
||||
void SaveCompressed(fs::path path) const {
|
||||
// Three regions to keep file format identical to the templated
|
||||
// variant; the data region is empty (skipped on the GPU path).
|
||||
std::array<std::span<const std::byte>, 3> streams = {
|
||||
std::as_bytes(std::span(vertexes)),
|
||||
std::as_bytes(std::span(indexes)),
|
||||
std::span<const std::byte>{},
|
||||
};
|
||||
Compression::CompressedBlob blob = Compression::CompressStreams(streams);
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file.write(MeshAssetFormat::magic, 4);
|
||||
std::uint32_t version = MeshAssetFormat::version;
|
||||
std::uint32_t vc = static_cast<std::uint32_t>(vertexes.size());
|
||||
std::uint32_t ic = static_cast<std::uint32_t>(indexes.size());
|
||||
std::uint32_t dc = 0;
|
||||
std::uint32_t stride = 0;
|
||||
file.write(reinterpret_cast<const char*>(&version), sizeof(version));
|
||||
file.write(reinterpret_cast<const char*>(&vc), sizeof(vc));
|
||||
file.write(reinterpret_cast<const char*>(&ic), sizeof(ic));
|
||||
file.write(reinterpret_cast<const char*>(&dc), sizeof(dc));
|
||||
file.write(reinterpret_cast<const char*>(&stride), sizeof(stride));
|
||||
Compression::WriteBlob(file, blob);
|
||||
}
|
||||
|
||||
static MeshAsset<void> Load(fs::path path) {
|
||||
MeshAsset<void> mesh;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue