10#include "hellfire/utilities/SerializerUtils.h"
14 std::ofstream file(filepath, std::ios::binary);
16 std::cerr <<
"MaterialSerializer: Cannot open file for writing: " << filepath << std::endl;
24 write_binary_string(file, mat.name);
27 write_binary(file, mat.diffuse_color);
28 write_binary(file, mat.ambient_color);
29 write_binary(file, mat.specular_color);
30 write_binary(file, mat.emissive_color);
39 write_binary(file, mat.uv_scale);
40 write_binary(file, mat.uv_offset);
48 const uint32_t texture_count =
static_cast<uint32_t>(mat.texture_assets.size());
49 write_binary(file, texture_count);
51 for (
const auto &[type, asset_id]: mat.texture_assets) {
52 write_binary(file,
static_cast<uint32_t>(type));
53 write_binary(file, asset_id);
60 std::ifstream file(filepath, std::ios::binary);
62 std::cerr <<
"MaterialSerializer: Cannot open file: " << filepath << std::endl;
68 if (!read_and_validate_header(file,
MAGIC,
VERSION, version)) {
69 std::cerr <<
"MaterialSerializer: Invalid file header: " << filepath << std::endl;
76 if (!read_binary_string(file, mat.name))
return std::nullopt;
79 if (!read_binary(file, mat.diffuse_color))
return std::nullopt;
80 if (!read_binary(file, mat.ambient_color))
return std::nullopt;
81 if (!read_binary(file, mat.specular_color))
return std::nullopt;
82 if (!read_binary(file, mat.emissive_color))
return std::nullopt;
85 if (!read_binary(file, mat
.opacity))
return std::nullopt;
86 if (!read_binary(file, mat
.shininess))
return std::nullopt;
87 if (!read_binary(file, mat
.metallic))
return std::nullopt;
88 if (!read_binary(file, mat
.roughness))
return std::nullopt;
91 if (!read_binary(file, mat.uv_scale))
return std::nullopt;
92 if (!read_binary(file, mat.uv_offset))
return std::nullopt;
95 if (!read_binary(file, mat
.double_sided))
return std::nullopt;
96 if (!read_binary(file, mat
.alpha_blend))
return std::nullopt;
97 if (!read_binary(file, mat
.alpha_cutoff))
return std::nullopt;
100 uint32_t texture_count;
101 if (!read_binary(file, texture_count))
return std::nullopt;
103 for (uint32_t i = 0; i < texture_count; i++) {
107 if (!read_binary(file, type_raw))
return std::nullopt;
108 if (!read_binary(file, asset_id))
return std::nullopt;
110 mat.texture_assets[
static_cast<
TextureType>(type_raw)] = asset_id;
126 default:
return "unknown";
145 j[
"name"] = mat.name;
148 {
"diffuse", vec3_to_json(mat.diffuse_color)},
149 {
"ambient", vec3_to_json(mat.ambient_color)},
150 {
"specular", vec3_to_json(mat.specular_color)},
151 {
"emissive", vec3_to_json(mat.emissive_color)}
162 {
"scale", vec2_to_json(mat.uv_scale)},
163 {
"offset", vec2_to_json(mat.uv_offset)}
173 nlohmann::json textures = nlohmann::json::object();
174 for (
const auto &[type, asset_id]: mat.texture_assets) {
175 textures[texture_type_to_string(type)] = asset_id;
177 j[
"textures"] = textures;
179 std::ofstream file(filepath);
180 if (!file)
return false;
187 std::ifstream file(filepath);
188 if (!file)
return std::nullopt;
196 mat.name = j.value(
"name",
"Material");
199 if (j.contains(
"colors")) {
200 const auto &colors = j[
"colors"];
201 if (
auto v = json_get_vec3(colors,
"diffuse")) mat.diffuse_color = *v;
202 if (
auto v = json_get_vec3(colors,
"ambient")) mat.ambient_color = *v;
203 if (
auto v = json_get_vec3(colors,
"specular")) mat.specular_color = *v;
204 if (
auto v = json_get_vec3(colors,
"emissive")) mat.emissive_color = *v;
208 if (j.contains(
"properties")) {
209 const auto &props = j[
"properties"];
210 mat
.opacity = props.value(
"opacity", 1.0f);
211 mat
.shininess = props.value(
"shininess", 32.0f);
212 mat
.metallic = props.value(
"metallic", 0.0f);
213 mat
.roughness = props.value(
"roughness", 0.5f);
217 if (j.contains(
"uv")) {
218 const auto &uv = j[
"uv"];
219 if (
auto v = json_get_vec2(uv,
"scale")) mat.uv_scale = *v;
220 if (
auto v = json_get_vec2(uv,
"offset")) mat.uv_offset = *v;
224 if (j.contains(
"flags")) {
225 const auto &flags = j[
"flags"];
232 if (j.contains(
"textures") && j[
"textures"].is_object()) {
233 for (
const auto &[key, value]: j[
"textures"].items()) {
234 TextureType type = string_to_texture_type(key);
235 AssetID asset_id = value.get<AssetID>();
236 mat.texture_assets[type] = asset_id;
241 }
catch (
const std::exception &e) {
242 std::cerr <<
"MaterialSerializer: JSON parse error: " << e.what() << std::endl;
static constexpr uint32_t VERSION
static constexpr uint32_t MAGIC
static bool save(const std::filesystem::path &filepath, const MaterialData &material)
static bool save_json(const std::filesystem::path &filepath, const MaterialData &material)
static const char * texture_type_to_string(TextureType type)
static TextureType string_to_texture_type(const std::string &str)
Serializable material data (separate from runtime Material class)