#include "scene_serialize.h" #include "scene_render.h" #include "../ASM/math_c_fallback.h" #include #include #include #include #ifndef PI #define PI 3.14159265f #endif static int node_index(Scene* scene, SceneNode* node) { if (!scene || !node) return -1; return (int)(node - scene->nodes); } static const char* mesh_type_name(MeshType t) { switch (t) { case MESH_CUBE: return "CUBE"; case MESH_SPHERE: return "SPHERE"; case MESH_PLANE: return "PLANE"; case MESH_OBJ: return "OBJ"; default: return "NONE"; } } static MeshType parse_mesh_type(const char* s) { if (!s) return MESH_NONE; if (strcmp(s, "CUBE") == 0) return MESH_CUBE; if (strcmp(s, "SPHERE") == 0) return MESH_SPHERE; if (strcmp(s, "PLANE") == 0) return MESH_PLANE; if (strcmp(s, "OBJ") == 0) return MESH_OBJ; return MESH_NONE; } static void write_node(FILE* f, Scene* scene, SceneNode* node) { if (!node) return; int parent = (node == scene->root) ? -1 : node_index(scene, node->parent); MeshRenderer* mr = scene_node_get_mesh_renderer(node); MeshType type = mr ? mr->type : MESH_NONE; const char* path = (mr && mr->path[0]) ? mr->path : "-"; float ex = 0.0f, ey = 0.0f, ez = 0.0f; quat_to_euler(&node->rotation, &ex, &ey, &ez); fprintf(f, "%s %d %s %s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n", node->name, parent, mesh_type_name(type), path, node->position.x, node->position.y, node->position.z, ex * 180.0f / PI, ey * 180.0f / PI, ez * 180.0f / PI, node->scale.x, node->scale.y, node->scale.z); for (int i = 0; i < node->child_count; i++) { write_node(f, scene, node->children[i]); } } int scene_save(Scene* scene, const char* path) { if (!scene || !path) return 0; FILE* f = fopen(path, "w"); if (!f) return 0; fprintf(f, "LITY3D_SCENE 1\n"); write_node(f, scene, scene->root); fclose(f); return 1; } static Mesh* create_mesh_for_type(MeshType type, ID3D11Device* dev, const char* path) { switch (type) { case MESH_CUBE: return mesh_create_cube(dev); case MESH_SPHERE: return mesh_create_sphere(dev, 1.0f, 16); case MESH_PLANE: return mesh_create_plane(dev, 10.0f); case MESH_OBJ: return path ? mesh_load_obj(dev, path) : NULL; default: return NULL; } } Scene* scene_load(const char* path, ID3D11Device* dev, Shader* default_shader) { FILE* f = fopen(path, "r"); if (!f) return NULL; char line[512]; if (!fgets(line, sizeof(line), f)) { fclose(f); return NULL; } if (strncmp(line, "LITY3D_SCENE", 10) != 0) { fclose(f); return NULL; } Scene* scene = (Scene*)malloc(sizeof(Scene)); if (!scene) { fclose(f); return NULL; } scene_init(scene); int capacity = 64; SceneNode** nodes = (SceneNode**)malloc(sizeof(SceneNode*) * capacity); int count = 0; while (fgets(line, sizeof(line), f)) { char name[64]; char type_str[16]; char path_str[256]; int parent_id; float px, py, pz, degx, degy, degz, sx, sy, sz; if (sscanf(line, "%63s %d %15s %255s %f %f %f %f %f %f %f %f %f", name, &parent_id, type_str, path_str, &px, &py, &pz, °x, °y, °z, &sx, &sy, &sz) != 13) { continue; } if (count >= capacity) { capacity *= 2; nodes = (SceneNode**)realloc(nodes, sizeof(SceneNode*) * capacity); } SceneNode* parent = (parent_id < 0) ? scene->root : nodes[parent_id]; SceneNode* node = scene_create_node(scene, name); if (!node) continue; if (parent) scene_set_parent(node, parent); node->position = (Vec3){px, py, pz}; node->scale = (Vec3){sx, sy, sz}; quat_from_euler(degx * PI / 180.0f, degy * PI / 180.0f, degz * PI / 180.0f, &node->rotation); MeshType type = parse_mesh_type(type_str); if (type != MESH_NONE) { const char* mesh_path = (strcmp(path_str, "-") == 0) ? NULL : path_str; Mesh* mesh = create_mesh_for_type(type, dev, mesh_path); if (mesh) { Material* mat = material_create(default_shader, NULL); MeshRenderer* mr = mesh_renderer_create(type, mesh, mat); if (mesh_path) strncpy(mr->path, mesh_path, sizeof(mr->path) - 1); scene_node_set_mesh_renderer(node, mr); } } nodes[count] = node; count++; } free(nodes); fclose(f); scene_update(scene); return scene; }