diff --git a/CMakeLists.txt b/CMakeLists.txt index fd50d73..2ffb3df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set(ENGINE_SOURCES Engine/Rendering/mesh.c Engine/Rendering/texture.c Engine/Rendering/camera.c + Engine/Scene/scene_graph.c Engine/ECS/world.c Engine/Input/input.c Engine/Physics/physics.c diff --git a/Engine/Scene/scene_graph.c b/Engine/Scene/scene_graph.c new file mode 100644 index 0000000..b5f55d5 --- /dev/null +++ b/Engine/Scene/scene_graph.c @@ -0,0 +1,226 @@ +// ============================================================================ +// scene_graph.c - 场景图实现 +// ============================================================================ + +#include "scene_graph.h" +#include +#include +#include + +void scene_init(Scene* scene) { + memset(scene, 0, sizeof(Scene)); + scene->next_id = 1; + // 创建根节点 + scene->root = &scene->nodes[0]; + memset(scene->root, 0, sizeof(SceneNode)); + scene->root->id = scene->next_id++; + strcpy(scene->root->name, "Root"); + scene->root->scale = (Vec3){1, 1, 1}; + scene->root->visible = 1; + scene->root->dirty = 1; + scene->node_count = 1; +} + +void scene_destroy(Scene* scene) { + // 清空子节点引用 (不释放静态数组) + for (int i = 0; i < scene->node_count; i++) { + scene->nodes[i].parent = NULL; + scene->nodes[i].child_count = 0; + } + scene->node_count = 0; +} + +SceneNode* scene_create_node(Scene* scene, const char* name) { + if (scene->node_count >= MAX_NODES) return NULL; + SceneNode* node = &scene->nodes[scene->node_count++]; + memset(node, 0, sizeof(SceneNode)); + node->id = scene->next_id++; + strncpy(node->name, name, 63); + node->scale = (Vec3){1, 1, 1}; + node->visible = 1; + node->dirty = 1; + return node; +} + +void scene_destroy_node(Scene* scene, SceneNode* node) { + if (!node || node == scene->root) return; + // 移除子引用 + if (node->parent) { + scene_remove_child(node->parent, node); + } + // 递归销毁子节点 + while (node->child_count > 0) { + scene_destroy_node(scene, node->children[0]); + } + node->id = 0; // 标记为空 +} + +SceneNode* scene_find_node(Scene* scene, int id) { + for (int i = 0; i < scene->node_count; i++) { + if (scene->nodes[i].id == id) return &scene->nodes[i]; + } + return NULL; +} + +SceneNode* scene_find_by_name(Scene* scene, const char* name) { + for (int i = 0; i < scene->node_count; i++) { + if (strcmp(scene->nodes[i].name, name) == 0) return &scene->nodes[i]; + } + return NULL; +} + +void scene_set_parent(SceneNode* child, SceneNode* parent) { + if (!child || !parent || child == parent) return; + if (child->parent) scene_remove_child(child->parent, child); + child->parent = parent; + if (parent->child_count < MAX_CHILDREN) { + parent->children[parent->child_count++] = child; + } + child->dirty = 1; +} + +void scene_add_child(SceneNode* parent, SceneNode* child) { + scene_set_parent(child, parent); +} + +void scene_remove_child(SceneNode* parent, SceneNode* child) { + if (!parent || !child) return; + for (int i = 0; i < parent->child_count; i++) { + if (parent->children[i] == child) { + parent->children[i] = parent->children[parent->child_count - 1]; + parent->child_count--; + child->parent = NULL; + child->dirty = 1; + return; + } + } +} + +void scene_set_position(SceneNode* node, float x, float y, float z) { + node->position = (Vec3){x, y, z}; + node->dirty = 1; +} + +void scene_set_rotation_euler(SceneNode* node, float rx, float ry, float rz) { + // 欧拉角转四元数 (YXZ 顺序) + float cr = cosf(rx * 0.5f), sr = sinf(rx * 0.5f); + float cp = cosf(ry * 0.5f), sp = sinf(ry * 0.5f); + float cy = cosf(rz * 0.5f), sy = sinf(rz * 0.5f); + node->rotation = (Quat){ + sr * cp * cy - cr * sp * sy, + cr * sp * cy + sr * cp * sy, + cr * cp * sy - sr * sp * cy, + cr * cp * cy + sr * sp * sy + }; + node->dirty = 1; +} + +void scene_set_scale(SceneNode* node, float sx, float sy, float sz) { + node->scale = (Vec3){sx, sy, sz}; + node->dirty = 1; +} + +void scene_set_rotation_quat(SceneNode* node, const Quat* q) { + node->rotation = *q; + node->dirty = 1; +} + +void scene_mark_dirty(SceneNode* node) { + node->dirty = 1; + for (int i = 0; i < node->child_count; i++) { + scene_mark_dirty(node->children[i]); + } +} + +static void update_local_matrix(SceneNode* node) { + // 旋转矩阵 + Mat4 rot; + quat_to_matrix(&node->rotation, &rot); + + // 缩放矩阵 + Mat4 scl; + mat4_identity(&scl); + scl.m[0][0] = node->scale.x; + scl.m[1][1] = node->scale.y; + scl.m[2][2] = node->scale.z; + + // 平移矩阵 + Mat4 trl; + mat4_translate(node->position.x, node->position.y, node->position.z, &trl); + + // local = trl * rot * scl + Mat4 tmp; + mat4_multiply(&rot, &scl, &tmp); + mat4_multiply(&trl, &tmp, &node->local_matrix); +} + +static void update_world_matrices(SceneNode* node) { + if (node->dirty) { + update_local_matrix(node); + if (node->parent) { + mat4_multiply(&node->parent->world_matrix, &node->local_matrix, &node->world_matrix); + } else { + node->world_matrix = node->local_matrix; + } + node->dirty = 0; + } + for (int i = 0; i < node->child_count; i++) { + update_world_matrices(node->children[i]); + } +} + +void scene_update(Scene* scene) { + if (scene->root) { + update_world_matrices(scene->root); + } +} + +void scene_get_world_position(SceneNode* node, Vec3* out) { + out->x = node->world_matrix.m[3][0]; + out->y = node->world_matrix.m[3][1]; + out->z = node->world_matrix.m[3][2]; +} + +void scene_get_world_rotation(SceneNode* node, Quat* out) { + // 从世界矩阵提取四元数 + Mat4 m = node->world_matrix; + float tr = m.m[0][0] + m.m[1][1] + m.m[2][2]; + if (tr > 0) { + float s = 0.5f / sqrtf(tr + 1.0f); + out->w = 0.25f / s; + out->x = (m.m[2][1] - m.m[1][2]) * s; + out->y = (m.m[0][2] - m.m[2][0]) * s; + out->z = (m.m[1][0] - m.m[0][1]) * s; + } else if (m.m[0][0] > m.m[1][1] && m.m[0][0] > m.m[2][2]) { + float s = 2.0f * sqrtf(1.0f + m.m[0][0] - m.m[1][1] - m.m[2][2]); + out->w = (m.m[2][1] - m.m[1][2]) / s; + out->x = 0.25f * s; + out->y = (m.m[0][1] + m.m[1][0]) / s; + out->z = (m.m[0][2] + m.m[2][0]) / s; + } else if (m.m[1][1] > m.m[2][2]) { + float s = 2.0f * sqrtf(1.0f + m.m[1][1] - m.m[0][0] - m.m[2][2]); + out->w = (m.m[0][2] - m.m[2][0]) / s; + out->x = (m.m[0][1] + m.m[1][0]) / s; + out->y = 0.25f * s; + out->z = (m.m[1][2] + m.m[2][1]) / s; + } else { + float s = 2.0f * sqrtf(1.0f + m.m[2][2] - m.m[0][0] - m.m[1][1]); + out->w = (m.m[1][0] - m.m[0][1]) / s; + out->x = (m.m[0][2] + m.m[2][0]) / s; + out->y = (m.m[1][2] + m.m[2][1]) / s; + out->z = 0.25f * s; + } +} + +void scene_get_world_scale(SceneNode* node, Vec3* out) { + // 从世界矩阵提取缩放 (各列向量的长度) + out->x = sqrtf(node->world_matrix.m[0][0] * node->world_matrix.m[0][0] + + node->world_matrix.m[0][1] * node->world_matrix.m[0][1] + + node->world_matrix.m[0][2] * node->world_matrix.m[0][2]); + out->y = sqrtf(node->world_matrix.m[1][0] * node->world_matrix.m[1][0] + + node->world_matrix.m[1][1] * node->world_matrix.m[1][1] + + node->world_matrix.m[1][2] * node->world_matrix.m[1][2]); + out->z = sqrtf(node->world_matrix.m[2][0] * node->world_matrix.m[2][0] + + node->world_matrix.m[2][1] * node->world_matrix.m[2][1] + + node->world_matrix.m[2][2] * node->world_matrix.m[2][2]); +} diff --git a/Engine/Scene/scene_graph.h b/Engine/Scene/scene_graph.h new file mode 100644 index 0000000..2d06eeb --- /dev/null +++ b/Engine/Scene/scene_graph.h @@ -0,0 +1,77 @@ +#pragma once + +// ============================================================================ +// scene_graph.h - 场景图: 节点树 + 变换继承 +// ============================================================================ + +#include "../ASM/math_c_fallback.h" +#include + +#define MAX_CHILDREN 64 +#define MAX_NODES 1024 + +// 场景节点 +typedef struct SceneNode { + int id; + char name[64]; + + // 本地变换 + Vec3 position; + Quat rotation; + Vec3 scale; + + // 世界矩阵 (每帧由 scene_update 计算) + Mat4 world_matrix; + Mat4 local_matrix; + + // 层级 + struct SceneNode* parent; + struct SceneNode* children[MAX_CHILDREN]; + int child_count; + + // 标志 + int visible; + int dirty; // 需要重新计算矩阵 + + // 用户数据 + void* user_data; + int user_type; +} SceneNode; + +// 场景 +typedef struct Scene { + SceneNode nodes[MAX_NODES]; + int node_count; + SceneNode* root; + int next_id; +} Scene; + +// 初始化/销毁 +void scene_init(Scene* scene); +void scene_destroy(Scene* scene); + +// 节点管理 +SceneNode* scene_create_node(Scene* scene, const char* name); +void scene_destroy_node(Scene* scene, SceneNode* node); +SceneNode* scene_find_node(Scene* scene, int id); +SceneNode* scene_find_by_name(Scene* scene, const char* name); + +// 层级 +void scene_set_parent(SceneNode* child, SceneNode* parent); +void scene_add_child(SceneNode* parent, SceneNode* child); +void scene_remove_child(SceneNode* parent, SceneNode* child); + +// 变换 +void scene_set_position(SceneNode* node, float x, float y, float z); +void scene_set_rotation_euler(SceneNode* node, float rx, float ry, float rz); +void scene_set_scale(SceneNode* node, float sx, float sy, float sz); +void scene_set_rotation_quat(SceneNode* node, const Quat* q); +void scene_mark_dirty(SceneNode* node); + +// 每帧更新 +void scene_update(Scene* scene); + +// 获取世界变换 +void scene_get_world_position(SceneNode* node, Vec3* out); +void scene_get_world_rotation(SceneNode* node, Quat* out); +void scene_get_world_scale(SceneNode* node, Vec3* out);