π₯ Camera 3D
Fase: 5 β TransiΓ§Γ£o Dimensional
Namespace: Caffeine::Render
Arquivo: src/render/Camera3D.hpp
Status: π
Planejado
RFs: RF5.5, RF5.6
VisΓ£o Geral
Camera3D com projeΓ§Γ£o perspectiva para renderizaΓ§Γ£o 3D. Coexiste com Camera2D (Fase 3) β o mesmo frame pode renderizar 2D (HUD, sprites) e 3D (ambiente, personagens) com cΓ’meras diferentes.
API Planejada
namespace Caffeine::Render {
// ============================================================================
// @brief CΓ’mera 3D com projeΓ§Γ£o perspectiva.
//
// Modos:
// - FPS: mouse look, WASD movement
// - Orbital: rotaΓ§Γ£o em torno de um ponto (editor, estratΓ©gia)
// - Follow: segue entidade com offset (terceira pessoa)
// ============================================================================
class Camera3D {
public:
Camera3D();
// ββ Matrizes βββββββββββββββββββββββββββββββββββββββββββββββ
Math::Mat4 viewMatrix() const;
Math::Mat4 projectionMatrix() const;
Math::Mat4 viewProjectionMatrix() const; // cached, dirty-flagged
// Frustum para culling (RF5.6)
Spatial::Frustum frustum() const;
// ββ ConversΓ£o de espaΓ§o ββββββββββββββββββββββββββββββββββββ
Math::Vec3 worldToScreen(Math::Vec3 worldPos) const;
Math::Vec3 screenToWorld(Math::Vec2 screenPos, f32 depth = 0.5f) const;
bool isVisible(const Spatial::AABB3D& bounds) const;
// ββ ConfiguraΓ§Γ£o perspectiva ββββββββββββββββββββββββββββββββ
void setFOV(f32 fovYDegrees);
void setAspect(f32 aspect);
void setNearFar(f32 nearPlane, f32 farPlane);
// ββ Transform ββββββββββββββββββββββββββββββββββββββββββββββ
void setPosition(Math::Vec3 pos);
void setRotation(Math::Quat rot);
void lookAt(Math::Vec3 eye, Math::Vec3 target,
Math::Vec3 up = {0, 1, 0});
// ββ FPS mode βββββββββββββββββββββββββββββββββββββββββββββββ
void rotateFPS(f32 deltaPitch, f32 deltaYaw); // graus
void moveFPS(Math::Vec3 localDelta); // espaΓ§o local
// ββ Orbital mode βββββββββββββββββββββββββββββββββββββββββββ
void orbit(f32 deltaAzimuth, f32 deltaElevation); // graus
void setOrbitTarget(Math::Vec3 target);
void setOrbitDistance(f32 distance);
void zoom(f32 delta);
// ββ Follow mode ββββββββββββββββββββββββββββββββββββββββββββ
void follow(ECS::Entity target, Math::Vec3 offset = {0, 2, -5},
f32 smoothing = 0.05f);
void update(f64 dt, const ECS::World& world);
// ββ Getters ββββββββββββββββββββββββββββββββββββββββββββββββ
Math::Vec3 position() const { return m_position; }
Math::Quat rotation() const { return m_rotation; }
Math::Vec3 forward() const;
Math::Vec3 right() const;
Math::Vec3 up() const;
f32 fov() const { return m_fovY; }
private:
Math::Mat4 calculateViewMatrix() const;
Math::Mat4 calculateProjectionMatrix() const;
Math::Vec3 m_position = {0, 0, -5};
Math::Quat m_rotation = Math::Quat::identity();
f32 m_fovY = 60.0f;
f32 m_aspect = 16.0f / 9.0f;
f32 m_near = 0.1f;
f32 m_far = 1000.0f;
// Follow
ECS::Entity m_followTarget = ECS::Entity::INVALID;
Math::Vec3 m_followOffset = {0, 2, -5};
f32 m_followSmoothing = 0.05f;
// Orbital
Math::Vec3 m_orbitTarget = {0, 0, 0};
f32 m_orbitDistance = 5.0f;
f32 m_azimuth = 0.0f; // graus
f32 m_elevation = 30.0f; // graus
mutable Math::Mat4 m_cachedVP;
mutable bool m_dirty = true;
};
} // namespace Caffeine::Render
MatemΓ‘tica da ProjeΓ§Γ£o Perspectiva
Projection Matrix (perspective):
f = 1 / tan(fovY/2)
[f/aspect, 0, 0, 0]
[0, f, 0, 0]
[0, 0, far/(far-near), 1]
[0, 0, -far*near/(far-near), 0]
View Matrix (lookAt):
forward = normalize(target - eye)
right = normalize(cross(forward, up))
up = cross(right, forward)
Mat4 lookAt = rotation(right, up, -forward) * translate(-eye)
Frustum Culling Integration
// Camera3D fornece Frustum para o Octree:
Spatial::Frustum frustum = camera3D.frustum();
octree.queryFrustum(frustum, visibleEntities);
// β apenas visibleEntities geram draw calls
Exemplos de Uso
// ββ Setup cΓ’mera perspectiva ββββββββββββββββββββββββββββββββββ
Caffeine::Render::Camera3D camera;
camera.setFOV(60.0f);
camera.setAspect(1280.0f / 720.0f);
camera.setNearFar(0.1f, 1000.0f);
camera.lookAt({0, 5, -10}, {0, 0, 0});
// ββ FPS camera ββββββββββββββββββββββββββββββββββββββββββββββββ
camera.rotateFPS(input.axisValue(Axis::LookY) * sensitivity,
input.axisValue(Axis::LookX) * sensitivity);
Vec3 moveDir = {
input.axisValue(Axis::MoveX),
0,
input.axisValue(Axis::MoveY)
};
camera.moveFPS(moveDir * moveSpeed * dt);
// ββ Follow (terceira pessoa) ββββββββββββββββββββββββββββββββββ
camera.follow(playerEntity, {0, 3, -6}, 0.05f);
camera.update(dt, world);
// ββ Orbital (editor/estratΓ©gia) βββββββββββββββββββββββββββββββ
camera.setOrbitTarget({0, 0, 0});
camera.setOrbitDistance(15.0f);
camera.orbit(deltaX * 0.5f, deltaY * 0.5f);
camera.zoom(scrollDelta);
// ββ Frustum culling βββββββββββββββββββββββββββββββββββββββββββ
auto visible = octree.queryFrustum(camera.frustum());
CoexistΓͺncia com Camera2D
// Frame com renderizaΓ§Γ£o 2D + 3D:
// Render 3D (mundo)
cmd->beginRenderPass(worldPassDesc);
meshSystem.renderWithCamera(camera3D, cmd); // perspectiva
cmd->endRenderPass();
// Render 2D (HUD sobreposto)
cmd->beginRenderPass(hudPassDesc);
batchRenderer.setCamera(camera2D); // ortho
batchRenderer.endFrame(cmd);
cmd->endRenderPass();
CritΓ©rio de AceitaΓ§Γ£o
DependΓͺncias
ReferΓͺncias
π₯ Camera 3D
VisΓ£o Geral
Camera3D com projeΓ§Γ£o perspectiva para renderizaΓ§Γ£o 3D. Coexiste com
Camera2D(Fase 3) β o mesmo frame pode renderizar 2D (HUD, sprites) e 3D (ambiente, personagens) com cΓ’meras diferentes.API Planejada
MatemΓ‘tica da ProjeΓ§Γ£o Perspectiva
Frustum Culling Integration
Exemplos de Uso
CoexistΓͺncia com Camera2D
CritΓ©rio de AceitaΓ§Γ£o
lookAtproduz view matrix correta (comparado com glm::lookAt)perspectiveproduz projection correta (comparado com glm::perspective)DependΓͺncias
ReferΓͺncias
docs/architecture_specs.mdβ Β§10 Camera System, RF5.5-5.6docs/fase3/camera.mdβ Camera2D (para coexistΓͺncia)docs/fase5/spatial-partitioning.mdβ Frustum culling via Octree