---
name: orbit_camera
kind: function
lang: cpp
domain: core
version: "1.0.0"
purity: pure
signature: "CameraMatrices orbit_camera_matrices(const OrbitCamera&); void orbit_camera_handle_drag(OrbitCamera&, ImVec2 drag_delta, float wheel)"
description: "Camara orbital pura — estado minimal (azimuth, elevation, distance, fov, aspect, near/far). Helpers: matrices view/proj (row-major float[16]) y handle_drag para integrar drag/wheel."
tags: [camera, orbit, math, matrix, lookat, perspective, 3d]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [imgui]
tested: false
tests: []
test_file_path: ""
file_path: "cpp/functions/core/orbit_camera.cpp"
framework: imgui
params:
  - name: cam
    desc: "OrbitCamera in/out: azimuth (rad), elevation (rad clamped ±π/2-eps), distance, fov (deg), aspect, near/far"
  - name: drag_delta
    desc: "ImVec2 desplazamiento del mouse desde la ultima frame (px). dx→azimuth, dy→elevation con sensibilidad 0.01 rad/px"
  - name: wheel
    desc: "Float scroll wheel (Imgui::GetIO().MouseWheel). distance *= (1 - wheel*0.1), clamp >0.1"
output: "orbit_camera_matrices: CameraMatrices con view (lookAt eye→origin, up=Y) y proj (perspective). Ambas row-major; al pasar a glUniformMatrix4fv usar transpose=GL_TRUE. orbit_camera_handle_drag: muta cam in-place, sin allocacion."
---

# orbit_camera

Camara orbital trivial para inspeccionar geometria 3D. Mantiene un objetivo fijo en el origen y rota la posicion del ojo en una esfera de radio `distance`.

## Convenciones

- **Azimuth = 0, elevation = 0** → ojo en `+Z`, mirando hacia `-Z`.
- **Up vector** = `+Y`. Right-handed.
- **Matrices row-major**: al subir a OpenGL, usar `glUniformMatrix4fv(loc, 1, GL_TRUE, &m.view[0])`.
- Sin glm: ~50 LOC, sin dependencias mas alla de `<cmath>`.

## Uso tipico

```cpp
fn::core::OrbitCamera cam;
cam.aspect = (float)w / (float)h;

// En el render loop:
auto m = fn::core::orbit_camera_matrices(cam);
glUniformMatrix4fv(loc_view, 1, GL_TRUE, m.view);
glUniformMatrix4fv(loc_proj, 1, GL_TRUE, m.proj);

// Si el panel esta activo:
if (ImGui::IsItemActive()) {
    fn::core::orbit_camera_handle_drag(
        cam,
        ImGui::GetIO().MouseDelta,
        ImGui::GetIO().MouseWheel
    );
}
```

## Notas

- Elevation se clampea a `±π/2 - 1e-3` para evitar flip de la up vector cuando se mira desde polos.
- Distance minima = 0.1 (impide cruzar el origen con el wheel).
- Si necesitas un target distinto al origen, suma `target` a `eye` y pasa `target` a la lookAt — el helper actual mira fijo a `(0,0,0)` por simplicidad.
