281 lines
6.4 KiB
C
281 lines
6.4 KiB
C
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include <scene/component.h>
|
|||
|
|
#include <types/math/rect.h>
|
|||
|
|
#include <types/math/mat4.h>
|
|||
|
|
#include <types/math/vec2.h>
|
|||
|
|
|
|||
|
|
namespace extra2d {
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 相机组件
|
|||
|
|
*
|
|||
|
|
* 负责管理相机投影和视图矩阵,支持缩放、旋转和边界限制
|
|||
|
|
*/
|
|||
|
|
class CameraComponent : public Component {
|
|||
|
|
public:
|
|||
|
|
static constexpr const char* TYPE_NAME = "Camera";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 投影类型
|
|||
|
|
*/
|
|||
|
|
enum class ProjectionType {
|
|||
|
|
Orthographic, // 正交投影
|
|||
|
|
Perspective // 透视投影
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 构造函数
|
|||
|
|
*/
|
|||
|
|
CameraComponent();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取组件类型名称
|
|||
|
|
* @return 类型名称
|
|||
|
|
*/
|
|||
|
|
const char* getTypeName() const override { return TYPE_NAME; }
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 投影设置
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置投影类型
|
|||
|
|
* @param type 投影类型
|
|||
|
|
*/
|
|||
|
|
void setProjectionType(ProjectionType type);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取投影类型
|
|||
|
|
* @return 投影类型
|
|||
|
|
*/
|
|||
|
|
ProjectionType getProjectionType() const { return projType_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置正交投影
|
|||
|
|
* @param left 左边界
|
|||
|
|
* @param right 右边界
|
|||
|
|
* @param bottom 下边界
|
|||
|
|
* @param top 上边界
|
|||
|
|
* @param near 近裁剪面
|
|||
|
|
* @param far 远裁剪面
|
|||
|
|
*/
|
|||
|
|
void setOrtho(float left, float right, float bottom, float top, float near, float far);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置透视投影
|
|||
|
|
* @param fov 视场角(度)
|
|||
|
|
* @param aspect 宽高比
|
|||
|
|
* @param near 近裁剪面
|
|||
|
|
* @param far 远裁剪面
|
|||
|
|
*/
|
|||
|
|
void setPerspective(float fov, float aspect, float near, float far);
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 变换属性(缩放、旋转)
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置缩放级别
|
|||
|
|
* @param zoom 缩放值(1.0为正常大小,>1放大,<1缩小)
|
|||
|
|
*/
|
|||
|
|
void setZoom(float zoom);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取缩放级别
|
|||
|
|
* @return 缩放值
|
|||
|
|
*/
|
|||
|
|
float getZoom() const { return zoom_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置旋转角度
|
|||
|
|
* @param degrees 旋转角度(度数)
|
|||
|
|
*/
|
|||
|
|
void setRotation(float degrees);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取旋转角度
|
|||
|
|
* @return 旋转角度(度数)
|
|||
|
|
*/
|
|||
|
|
float getRotation() const { return rotation_; }
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 矩阵获取
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取视图矩阵
|
|||
|
|
* @return 视图矩阵
|
|||
|
|
*/
|
|||
|
|
Mat4 getViewMatrix() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取投影矩阵
|
|||
|
|
* @return 投影矩阵
|
|||
|
|
*/
|
|||
|
|
Mat4 getProjectionMatrix() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取视图投影矩阵
|
|||
|
|
* @return 视图投影矩阵
|
|||
|
|
*/
|
|||
|
|
Mat4 getViewProjectionMatrix() const;
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 坐标转换
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将屏幕坐标转换为世界坐标
|
|||
|
|
* @param screenPos 屏幕坐标
|
|||
|
|
* @return 世界坐标
|
|||
|
|
*/
|
|||
|
|
Vec2 screenToWorld(const Vec2& screenPos) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将屏幕坐标转换为世界坐标
|
|||
|
|
* @param x 屏幕X坐标
|
|||
|
|
* @param y 屏幕Y坐标
|
|||
|
|
* @return 世界坐标
|
|||
|
|
*/
|
|||
|
|
Vec2 screenToWorld(float x, float y) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将世界坐标转换为屏幕坐标
|
|||
|
|
* @param worldPos 世界坐标
|
|||
|
|
* @return 屏幕坐标
|
|||
|
|
*/
|
|||
|
|
Vec2 worldToScreen(const Vec2& worldPos) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将世界坐标转换为屏幕坐标
|
|||
|
|
* @param x 世界X坐标
|
|||
|
|
* @param y 世界Y坐标
|
|||
|
|
* @return 屏幕坐标
|
|||
|
|
*/
|
|||
|
|
Vec2 worldToScreen(float x, float y) const;
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 视口
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置视口
|
|||
|
|
* @param viewport 视口矩形
|
|||
|
|
*/
|
|||
|
|
void setViewport(const Rect& viewport);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取视口
|
|||
|
|
* @return 视口矩形
|
|||
|
|
*/
|
|||
|
|
Rect getViewport() const { return viewport_; }
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 边界限制
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置相机边界限制
|
|||
|
|
* @param bounds 边界矩形
|
|||
|
|
*/
|
|||
|
|
void setBounds(const Rect& bounds);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 清除相机边界限制
|
|||
|
|
*/
|
|||
|
|
void clearBounds();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查是否有边界限制
|
|||
|
|
* @return 是否有边界限制
|
|||
|
|
*/
|
|||
|
|
bool hasBounds() const { return hasBounds_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将相机位置限制在边界内
|
|||
|
|
*/
|
|||
|
|
void clampToBounds();
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 移动相机
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 移动相机位置
|
|||
|
|
* @param offset 位置偏移量
|
|||
|
|
*/
|
|||
|
|
void move(const Vec2& offset);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 移动相机位置
|
|||
|
|
* @param x X方向偏移量
|
|||
|
|
* @param y Y方向偏移量
|
|||
|
|
*/
|
|||
|
|
void move(float x, float y);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将相机移动到目标位置
|
|||
|
|
* @param target 目标位置
|
|||
|
|
*/
|
|||
|
|
void lookAt(const Vec2& target);
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
/**
|
|||
|
|
* @brief 标记视图矩阵为脏
|
|||
|
|
*/
|
|||
|
|
void markViewDirty() { viewDirty_ = true; vpDirty_ = true; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 标记投影矩阵为脏
|
|||
|
|
*/
|
|||
|
|
void markProjDirty() { projDirty_ = true; vpDirty_ = true; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 更新视图矩阵
|
|||
|
|
*/
|
|||
|
|
void updateViewMatrix() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 更新投影矩阵
|
|||
|
|
*/
|
|||
|
|
void updateProjectionMatrix() const;
|
|||
|
|
|
|||
|
|
ProjectionType projType_ = ProjectionType::Orthographic;
|
|||
|
|
|
|||
|
|
// 投影参数
|
|||
|
|
float left_ = 0.0f;
|
|||
|
|
float right_ = 800.0f;
|
|||
|
|
float bottom_ = 600.0f;
|
|||
|
|
float top_ = 0.0f;
|
|||
|
|
float near_ = -1.0f;
|
|||
|
|
float far_ = 1.0f;
|
|||
|
|
|
|||
|
|
// 透视投影参数
|
|||
|
|
float fov_ = 60.0f;
|
|||
|
|
float aspect_ = 16.0f / 9.0f;
|
|||
|
|
|
|||
|
|
// 变换属性
|
|||
|
|
float zoom_ = 1.0f;
|
|||
|
|
float rotation_ = 0.0f;
|
|||
|
|
|
|||
|
|
// 视口
|
|||
|
|
Rect viewport_;
|
|||
|
|
|
|||
|
|
// 边界限制
|
|||
|
|
Rect bounds_;
|
|||
|
|
bool hasBounds_ = false;
|
|||
|
|
|
|||
|
|
// 缓存矩阵(mutable 用于 const 方法中延迟计算)
|
|||
|
|
mutable Mat4 viewMatrix_ = Mat4(1.0f);
|
|||
|
|
mutable Mat4 projMatrix_ = Mat4(1.0f);
|
|||
|
|
mutable Mat4 vpMatrix_ = Mat4(1.0f);
|
|||
|
|
|
|||
|
|
// 脏标记
|
|||
|
|
mutable bool viewDirty_ = true;
|
|||
|
|
mutable bool projDirty_ = true;
|
|||
|
|
mutable bool vpDirty_ = true;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace extra2d
|