194 lines
7.4 KiB
Text
194 lines
7.4 KiB
Text
|
|
module;
|
||
|
|
|
||
|
|
#include <cstdint>
|
||
|
|
#include <string>
|
||
|
|
#include <vector>
|
||
|
|
#include <filesystem>
|
||
|
|
#include <unordered_map>
|
||
|
|
#include <iostream>
|
||
|
|
#include <functional>
|
||
|
|
#include <fstream>
|
||
|
|
#define STB_IMAGE_IMPLEMENTATION
|
||
|
|
#include "stb_image.h"
|
||
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||
|
|
#include "stb_image_write.h"
|
||
|
|
|
||
|
|
|
||
|
|
export module Crafter.Asset:Asset;
|
||
|
|
namespace fs = std::filesystem;
|
||
|
|
|
||
|
|
struct __attribute__((packed)) Float3 {
|
||
|
|
float x;
|
||
|
|
float y;
|
||
|
|
float z;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct __attribute__((packed)) Float2 {
|
||
|
|
float x;
|
||
|
|
float y;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct __attribute__((packed)) VertexUV {
|
||
|
|
Float3 position;
|
||
|
|
Float2 uv;
|
||
|
|
};
|
||
|
|
|
||
|
|
void SplitString(const std::string& s, const char delimiter, std::vector<std::string>& tokens) {
|
||
|
|
std::istringstream iss(s);
|
||
|
|
std::string token;
|
||
|
|
|
||
|
|
while (std::getline(iss, token, delimiter)) {
|
||
|
|
tokens.push_back(token);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
uint32_t ProcessVertex(std::vector<VertexUV>& verticies, std::vector<Float3> positions, std::vector<Float2> uvs, uint32_t posIndex, uint32_t uvIndex) {
|
||
|
|
Float3 pos = positions[posIndex - 1];
|
||
|
|
Float2 uv = uvs[uvIndex - 1];
|
||
|
|
for (uint32_t i = 0; i < verticies.size(); i++) {
|
||
|
|
VertexUV vert = verticies[i];
|
||
|
|
if (vert.position.x == pos.x && vert.position.y == pos.y && vert.position.z == pos.z && vert.uv.x == uv.x && vert.uv.y == uv.y) {
|
||
|
|
return i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
verticies.push_back({ pos ,uv });
|
||
|
|
return verticies.size() - 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
export namespace Crafter {
|
||
|
|
std::unordered_map<std::string, std::function<std::vector<char>(fs::path)>> serializers = {
|
||
|
|
{
|
||
|
|
"PNG:Crafter.Graphics.TextureR8B8G8A8",
|
||
|
|
[](fs::path file) {
|
||
|
|
int x,y,n;
|
||
|
|
unsigned char *imageData = stbi_load(file.generic_string().c_str(),&x, &y, &n, 4);
|
||
|
|
std::uint32_t x2 = x;
|
||
|
|
std::uint32_t y2 = y;
|
||
|
|
std::vector<char> data(sizeof(std::uint32_t)+sizeof(std::uint32_t)+(x*y*4));
|
||
|
|
memcpy(&data[0], &x2, sizeof(std::uint32_t));
|
||
|
|
memcpy(&data[sizeof(std::uint32_t)], &y2, sizeof(std::uint32_t));
|
||
|
|
memcpy(&data[sizeof(std::uint32_t)*2], imageData, x*y*4);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"OBJ:Crafter.Graphics.Mesh",
|
||
|
|
[](fs::path path) {
|
||
|
|
std::ifstream file(path);
|
||
|
|
|
||
|
|
std::string line;
|
||
|
|
std::vector<Float3> positions;
|
||
|
|
std::vector<std::uint32_t> indices;
|
||
|
|
|
||
|
|
while (std::getline(file, line)) {
|
||
|
|
if (line.substr(0, 1) == "v") {
|
||
|
|
std::istringstream iss(line.substr(2));
|
||
|
|
Float3 pos{0,0,0};
|
||
|
|
iss >> pos.x >> pos.y >> pos.z;
|
||
|
|
positions.push_back(pos);
|
||
|
|
}
|
||
|
|
else if (line.substr(0, 1) == "f") {
|
||
|
|
std::vector<std::string> tokens;
|
||
|
|
SplitString(line.substr(2), ' ', tokens);
|
||
|
|
for (size_t i = 0; i < 3; ++i) {
|
||
|
|
indices.push_back(std::stoul(tokens[i])-1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
file.close();
|
||
|
|
|
||
|
|
std::vector<char> buffer((positions.size()*sizeof(Float3))+(indices.size()*sizeof(std::uint32_t))+sizeof(std::uint32_t)+sizeof(std::uint32_t));
|
||
|
|
std::uint32_t vertSize = positions.size();
|
||
|
|
std::uint32_t indexSize = indices.size();
|
||
|
|
memcpy(&buffer[0], &vertSize, sizeof(std::uint32_t));
|
||
|
|
memcpy(&buffer[sizeof(std::uint32_t)], &indexSize, sizeof(std::uint32_t));
|
||
|
|
memcpy(&buffer[sizeof(std::uint32_t)*2], positions.data(), positions.size()*sizeof(Float3));
|
||
|
|
memcpy(&buffer[positions.size()*sizeof(Float3)+sizeof(std::uint32_t)+sizeof(std::uint32_t)], indices.data(), indices.size()*sizeof(std::uint32_t));
|
||
|
|
|
||
|
|
return buffer;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"OBJ:Crafter.Graphics.MeshUV",
|
||
|
|
[](fs::path path) {
|
||
|
|
std::ifstream file(path);
|
||
|
|
|
||
|
|
std::string line;
|
||
|
|
|
||
|
|
std::vector<Float3> positions;
|
||
|
|
std::vector<Float2> uvs;
|
||
|
|
std::vector<VertexUV> verticies;
|
||
|
|
std::vector<uint32_t> indicies;
|
||
|
|
|
||
|
|
while (std::getline(file, line)) {
|
||
|
|
if (line.substr(0, 2) == "vt") {
|
||
|
|
std::istringstream iss(line.substr(3));
|
||
|
|
Float2 uv{0,0};
|
||
|
|
iss >> uv.x >> uv.y;
|
||
|
|
uvs.push_back(uv);
|
||
|
|
}
|
||
|
|
else if (line.substr(0, 1) == "v") {
|
||
|
|
std::istringstream iss(line.substr(2));
|
||
|
|
Float3 pos{0,0,0};
|
||
|
|
iss >> pos.x >> pos.y >> pos.z;
|
||
|
|
positions.push_back(pos);
|
||
|
|
}
|
||
|
|
else if (line.substr(0, 1) == "f") {
|
||
|
|
std::vector<std::string> tokens;
|
||
|
|
SplitString(line.substr(2), ' ', tokens);
|
||
|
|
|
||
|
|
for (size_t i = 0; i < 3; ++i) {
|
||
|
|
size_t slashPos = tokens[i].find('/');
|
||
|
|
indicies.push_back(ProcessVertex(verticies, positions, uvs, std::stoul(tokens[i].substr(0, slashPos)), std::stoul(tokens[i].substr(slashPos + 1))));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
file.close();
|
||
|
|
|
||
|
|
std::vector<char> buffer((verticies.size()*sizeof(VertexUV))+(indicies.size()*sizeof(std::uint32_t))+sizeof(std::uint32_t)+sizeof(std::uint32_t));
|
||
|
|
std::uint32_t vertSize = verticies.size();
|
||
|
|
std::uint32_t indexSize = indicies.size();
|
||
|
|
memcpy(&buffer[0], &vertSize, sizeof(std::uint32_t));
|
||
|
|
memcpy(&buffer[sizeof(std::uint32_t)], &indexSize, sizeof(std::uint32_t));
|
||
|
|
memcpy(&buffer[sizeof(std::uint32_t)*2], verticies.data(), verticies.size()*sizeof(VertexUV));
|
||
|
|
memcpy(&buffer[verticies.size()*sizeof(VertexUV)+sizeof(std::uint32_t)+sizeof(std::uint32_t)], indicies.data(), indicies.size()*sizeof(std::uint32_t));
|
||
|
|
|
||
|
|
return buffer;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
std::unordered_map<std::string, std::function<void(fs::path, const void*)>> extractors = {
|
||
|
|
{
|
||
|
|
"Crafter.Graphics.TextureR8B8G8A8:PNG",
|
||
|
|
[](fs::path dst, const void* data) {
|
||
|
|
stbi_write_png(dst.generic_string().c_str(), reinterpret_cast<const std::uint32_t*>(data)[0], reinterpret_cast<const std::uint32_t*>(data)[1], 4, reinterpret_cast<const char*>(data)+(sizeof(std::uint32_t)*2), reinterpret_cast<const std::uint32_t*>(data)[0]*4);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
class AssetEntry {
|
||
|
|
public:
|
||
|
|
std::string name;
|
||
|
|
std::string type;
|
||
|
|
std::vector<char> data;
|
||
|
|
AssetEntry();
|
||
|
|
AssetEntry(std::string name, std::string type, std::vector<char> data);
|
||
|
|
AssetEntry(std::string name, std::string type, void* data);
|
||
|
|
};
|
||
|
|
class Asset {
|
||
|
|
public:
|
||
|
|
std::vector<AssetEntry> entries;
|
||
|
|
Asset();
|
||
|
|
Asset(std::vector<AssetEntry> entries);
|
||
|
|
void LoadFull(fs::path path);
|
||
|
|
void LoadHeaders(fs::path path);
|
||
|
|
void LoadSpecific(fs::path path, std::string entry);
|
||
|
|
void LoadSpecific(fs::path path, std::vector<std::string> entries);
|
||
|
|
void LoadSpecific(fs::path path, std::uint32_t entry);
|
||
|
|
void LoadSpecific(fs::path path, std::vector<std::uint32_t> entries);
|
||
|
|
void Save(fs::path path);
|
||
|
|
};
|
||
|
|
}
|