refresh: stack al día (vello 0.7 / wgpu 27 / parley 0.6) + motor 3D voxel
Re-sincroniza las fuentes desde el monorepo (estaba en vello 0.5/wgpu 24 y con la estructura vieja de eventloop) y suma el 3D: - bump del workspace a vello 0.7 / wgpu 27 / parley 0.6, + accesskit 0.24 / accesskit_winit 0.33 / vello_hybrid 0.0.9. - nuevos crates: llimphi-3d (voxels ray-march + mallas en un depth compartido, montable dentro de un View 2D vía set_viewport+scissor) y llimphi-voxel (world-gen, personajes, director de escenas) + shared/foreign-vox (puente .vox). - README: sección "Not just 2D — a 3D voxel engine" + GIF (docs/llimphi_voxel.gif). - excluido modules/allichay (arrastra deps fuera del alcance del front-door). - cargo check --workspace: verde. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
//! Cámara 3D — produce la matriz `view_proj` que el shader aplica a cada
|
||||
//! vértice. Convención de mano derecha y profundidad `0..1` (la de wgpu/
|
||||
//! Vulkan/Metal/DX12, **no** la `-1..1` de OpenGL).
|
||||
|
||||
use glam::{Mat4, Vec3};
|
||||
|
||||
/// Cámara en perspectiva. `eye` mira a `target` con `up` como vertical.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Camera3d {
|
||||
/// Posición del ojo en mundo.
|
||||
pub eye: Vec3,
|
||||
/// Punto al que mira.
|
||||
pub target: Vec3,
|
||||
/// Vector "arriba" (normalmente `Vec3::Y`).
|
||||
pub up: Vec3,
|
||||
/// Campo de visión vertical, en radianes.
|
||||
pub fovy_rad: f32,
|
||||
/// Plano cercano (`> 0`).
|
||||
pub znear: f32,
|
||||
/// Plano lejano.
|
||||
pub zfar: f32,
|
||||
}
|
||||
|
||||
impl Default for Camera3d {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
eye: Vec3::new(2.5, 2.0, 3.5),
|
||||
target: Vec3::ZERO,
|
||||
up: Vec3::Y,
|
||||
fovy_rad: 60_f32.to_radians(),
|
||||
znear: 0.1,
|
||||
// Generoso: cubre mundos voxel de cientos de unidades. Importa desde
|
||||
// que el pase de voxels escribe profundidad (`Scene3d`): un hit más
|
||||
// allá de `zfar` se clamparía a 1.0 y fallaría el depth test. Float32
|
||||
// de depth mantiene precisión de sobra en este rango para oclusión.
|
||||
zfar: 5000.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Camera3d {
|
||||
/// Cámara orbitando `target` a `dist`, con `yaw`/`pitch` en radianes.
|
||||
/// `yaw` gira alrededor del eje Y; `pitch` sube/baja (clamp suave para no
|
||||
/// cruzar los polos y degenerar el `up`).
|
||||
pub fn orbit(target: Vec3, yaw: f32, pitch: f32, dist: f32) -> Self {
|
||||
let lim = std::f32::consts::FRAC_PI_2 - 0.01;
|
||||
let pitch = pitch.clamp(-lim, lim);
|
||||
let (sy, cy) = yaw.sin_cos();
|
||||
let (sp, cp) = pitch.sin_cos();
|
||||
let offset = Vec3::new(cp * sy, sp, cp * cy) * dist;
|
||||
Self {
|
||||
eye: target + offset,
|
||||
target,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Cámara **libre / primera persona**: parada en `eye`, mirando según
|
||||
/// `yaw` (giro alrededor de Y) y `pitch` (cabeceo, clamped para no cruzar el
|
||||
/// cenit). Complementa a [`orbit`](Self::orbit): `orbit` mira un punto desde
|
||||
/// afuera (vista de paisaje), `fly` te pone *adentro* del mundo (vuelo / FPS).
|
||||
/// `yaw=0` mira hacia `+Z`.
|
||||
pub fn fly(eye: Vec3, yaw: f32, pitch: f32) -> Self {
|
||||
let lim = std::f32::consts::FRAC_PI_2 - 0.01;
|
||||
let pitch = pitch.clamp(-lim, lim);
|
||||
let (sy, cy) = yaw.sin_cos();
|
||||
let (sp, cp) = pitch.sin_cos();
|
||||
let dir = Vec3::new(cp * sy, sp, cp * cy);
|
||||
Self {
|
||||
eye,
|
||||
target: eye + dir,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Matriz `proj * view` lista para `mvp * vec4(pos, 1.0)` en el shader.
|
||||
/// `aspect` = ancho/alto del viewport en pixels.
|
||||
pub fn view_proj(&self, aspect: f32) -> Mat4 {
|
||||
let view = Mat4::look_at_rh(self.eye, self.target, self.up);
|
||||
// `perspective_rh` (no `_gl`): profundidad 0..1, la que espera wgpu.
|
||||
let proj = Mat4::perspective_rh(self.fovy_rad, aspect.max(1e-4), self.znear, self.zfar);
|
||||
proj * view
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user