Files
lity3d/Engine/Scene/scene_serialize.c
T

142 lines
4.6 KiB
C

#include "scene_serialize.h"
#include "scene_render.h"
#include "../ASM/math_c_fallback.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#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, &degx, &degy, &degz, &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;
}