// camera3d.hpp - Càmera 3D amb projecció en perspectiva en CPU // © 2026 JailDesigner // // La càmera viu en l'espai mundial (X dreta, Y amunt, Z davant). El mètode // project() pren un Vec3 mundial i torna les coordenades 2D en píxels lògics // de pantalla, més el factor d'escala focal/depth (útil per renderShape). // Si el punt queda darrere del near plane, torna std::nullopt. #pragma once #include #include "core/types.hpp" namespace Graphics { class Camera3D { public: struct ProjectedPoint { Vec2 screen; // Píxels lògics float scale; // focal / depth (escala visual a aquesta Z) float depth; // Profunditat en l'espai de càmera (cz) }; Camera3D(const Vec3& position, const Vec3& target, const Vec3& up_world, float fov_y_rad, float viewport_w, float viewport_h, float near_plane = 0.1F, float far_plane = 2000.0F); void setPosition(const Vec3& p); void setTarget(const Vec3& t); void setUpWorld(const Vec3& u); void setViewport(float w, float h); void setFovY(float fov_y_rad); [[nodiscard]] auto project(const Vec3& world) const -> std::optional; [[nodiscard]] auto position() const -> const Vec3& { return position_; } [[nodiscard]] auto forward() const -> const Vec3& { return forward_; } [[nodiscard]] auto nearPlane() const -> float { return near_; } [[nodiscard]] auto farPlane() const -> float { return far_; } private: void recomputeBasis(); void recomputeFocal(); Vec3 position_{}; Vec3 target_{}; Vec3 up_world_{}; Vec3 right_{.x = 1.0F, .y = 0.0F, .z = 0.0F}; Vec3 up_{.x = 0.0F, .y = 1.0F, .z = 0.0F}; Vec3 forward_{.x = 0.0F, .y = 0.0F, .z = 1.0F}; float fov_y_rad_{0.0F}; float viewport_w_{0.0F}; float viewport_h_{0.0F}; float near_{0.1F}; float far_{2000.0F}; float focal_{0.0F}; float centre_x_{0.0F}; float centre_y_{0.0F}; }; } // namespace Graphics