refactor: Transform 字段封装 + dirty 标记(对齐 UE USceneComponent 真实现)
- 修正上一版"全量暴力重算":UE 实为 dirty 标记 + 惰性计算,前提是 字段私有(SetRelativeLocation 等 setter 标脏 + 子级传播) - TransformComponent:SRT 字段私有化,Set/Get/World()/IsDirty 访问器; Set* 变更才标脏;AddRotationY 便捷接口 - Scene::UpdateTransforms 只重算脏实体——静止实体零成本; 层级(父子)传播在脏标记基础上扩展 - 迁移 Camera/SceneRenderer/main.cpp 到封装 API
This commit is contained in:
@@ -34,34 +34,49 @@ namespace Engine::ECS {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
// 世界变换:可编辑的 SRT 分量 + 派生的 world 矩阵。
|
||||
// 分量可直接读写(含直接改字段);world 由帧循环的
|
||||
// Scene::UpdateTransforms() 全量重算(UE transform-update 阶段
|
||||
// 模式),调用方永远不需要手动 Compose。渲染热路径只读 world。
|
||||
// 世界变换:UE USceneComponent 的 encapsulation 模式——
|
||||
// SRT 分量私有,所有写入口标脏;world 矩阵由帧循环的
|
||||
// Scene::UpdateTransforms() 只对脏的实体重算(transform-update
|
||||
// 阶段),并自动向未来的子层级传播。渲染热路径只读 World()。
|
||||
// 层级(父子变换)留给后续的层级同步系统。
|
||||
struct TransformComponent {
|
||||
glm::vec3 position{0.0f};
|
||||
glm::vec3 rotation{0.0f}; // 欧拉角(度),应用顺序 Y→X→Z
|
||||
glm::vec3 scale{1.0f};
|
||||
glm::mat4 world{1.0f};
|
||||
// ---- 读取 ----
|
||||
const glm::vec3& GetPosition() const { return m_position; }
|
||||
const glm::vec3& GetRotation() const { return m_rotation; } // 欧拉角(度)
|
||||
const glm::vec3& GetScale() const { return m_scale; }
|
||||
const glm::mat4& World() const { return m_world; } // 要求已由 UpdateTransforms 计算
|
||||
|
||||
TransformComponent& SetPosition(const glm::vec3& p) { position = p; return *this; }
|
||||
TransformComponent& SetRotation(const glm::vec3& r) { rotation = r; return *this; }
|
||||
TransformComponent& SetScale(const glm::vec3& s) { scale = s; return *this; }
|
||||
// ---- 写入(标脏,脏实体由 UpdateTransforms 重算)----
|
||||
TransformComponent& SetPosition(const glm::vec3& p) { if (m_position != p) { m_position = p; m_dirty = true; } return *this; }
|
||||
TransformComponent& SetRotation(const glm::vec3& r) { if (m_rotation != r) { m_rotation = r; m_dirty = true; } return *this; }
|
||||
TransformComponent& SetScale(const glm::vec3& s) { if (m_scale != s) { m_scale = s; m_dirty = true; } return *this; }
|
||||
|
||||
// SRT 分量 → world 矩阵(T * R * S)。
|
||||
// 由 UpdateTransforms 每帧全量调用;勿在用户代码手动调用
|
||||
// 便捷:原地修改单个欧拉角分量(度)
|
||||
TransformComponent& AddRotationY(f32 degY) { m_rotation.y += degY; m_dirty = true; return *this; }
|
||||
|
||||
bool IsDirty() const { return m_dirty; }
|
||||
|
||||
// SRT 分量 → world 矩阵(T * R * S),清除脏标记。
|
||||
// 由 Scene::UpdateTransforms 调用(或层级系统),勿手动
|
||||
TransformComponent& Compose()
|
||||
{
|
||||
const glm::mat4 t = glm::translate(glm::mat4(1.0f), position);
|
||||
const glm::mat4 t = glm::translate(glm::mat4(1.0f), m_position);
|
||||
const glm::mat4 r =
|
||||
glm::rotate(glm::mat4(1.0f), glm::radians(rotation.y), glm::vec3(0, 1, 0)) *
|
||||
glm::rotate(glm::mat4(1.0f), glm::radians(rotation.x), glm::vec3(1, 0, 0)) *
|
||||
glm::rotate(glm::mat4(1.0f), glm::radians(rotation.z), glm::vec3(0, 0, 1));
|
||||
const glm::mat4 s = glm::scale(glm::mat4(1.0f), scale);
|
||||
world = t * r * s;
|
||||
glm::rotate(glm::mat4(1.0f), glm::radians(m_rotation.y), glm::vec3(0, 1, 0)) *
|
||||
glm::rotate(glm::mat4(1.0f), glm::radians(m_rotation.x), glm::vec3(1, 0, 0)) *
|
||||
glm::rotate(glm::mat4(1.0f), glm::radians(m_rotation.z), glm::vec3(0, 0, 1));
|
||||
const glm::mat4 s = glm::scale(glm::mat4(1.0f), m_scale);
|
||||
m_world = t * r * s;
|
||||
m_dirty = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
glm::vec3 m_position{0.0f};
|
||||
glm::vec3 m_rotation{0.0f};
|
||||
glm::vec3 m_scale{1.0f};
|
||||
glm::mat4 m_world{1.0f};
|
||||
bool m_dirty = true; // 出生即脏:首次 UpdateTransforms 计算 world
|
||||
};
|
||||
|
||||
// 网格渲染体:引用共享的 Model 资产。
|
||||
|
||||
Reference in New Issue
Block a user