Add headless wgpu vision and camera controls
Some checks failed
CI / rust-skia (Rust only) (push) Has been cancelled
CI / required (push) Has been cancelled

This commit is contained in:
2026-08-22 11:36:34 +02:00
parent 0dd2ca5824
commit c101007362
19 changed files with 1250 additions and 56 deletions

View File

@@ -399,6 +399,7 @@ impl CameraFrame {
pub struct AgentManagerAgentMovementAgentCamera {
pub far: f32,
frame: Arc<Mutex<CameraFrame>>,
vertical_fov_radians: Arc<AtomicU32>,
}
impl fmt::Debug for AgentManagerAgentMovementAgentCamera {
@@ -406,6 +407,7 @@ impl fmt::Debug for AgentManagerAgentMovementAgentCamera {
formatter
.debug_struct("AgentCamera")
.field("far", &self.far)
.field("vertical_fov_radians", &self.vertical_fov_angle())
.field("frame", &*mutex(&self.frame))
.finish()
}
@@ -416,11 +418,20 @@ impl AgentManagerAgentMovementAgentCamera {
Ok(Self {
far: 128.0,
frame: Arc::new(Mutex::new(CameraFrame::default())),
vertical_fov_radians: Arc::new(AtomicU32::new(60.0_f32.to_radians().to_bits())),
})
}
fn from_frame(frame: Arc<Mutex<CameraFrame>>, far: f32) -> Self {
Self { far, frame }
fn from_frame(
frame: Arc<Mutex<CameraFrame>>,
vertical_fov_radians: Arc<AtomicU32>,
far: f32,
) -> Self {
Self {
far,
frame,
vertical_fov_radians,
}
}
pub fn look_at_with_vector3_vector3(
@@ -584,6 +595,21 @@ impl AgentManagerAgentMovementAgentCamera {
mutex(&self.frame).z_axis = value;
}
}
#[must_use]
pub fn vertical_fov_angle(&self) -> f32 {
f32::from_bits(self.vertical_fov_radians.load(Ordering::Acquire))
}
pub fn set_vertical_fov_angle(&self, value: f32) -> Result<(), Error> {
if !value.is_finite() || !(10.0_f32.to_radians()..=140.0_f32.to_radians()).contains(&value)
{
return Err(Error::Argument);
}
self.vertical_fov_radians
.store(value.to_bits(), Ordering::Release);
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -733,6 +759,7 @@ pub(crate) struct AgentMovementRuntime {
auto_reset_controls: AtomicBool,
update_interval: AtomicI32,
camera_frame: Arc<Mutex<CameraFrame>>,
vertical_fov_radians: Arc<AtomicU32>,
last_update: Mutex<LastUpdate>,
kinematics: RwLock<Kinematics>,
teleport: Mutex<TeleportState>,
@@ -805,6 +832,7 @@ impl AgentMovementRuntime {
auto_reset_controls: AtomicBool::new(false),
update_interval: AtomicI32::new(interval),
camera_frame: Arc::new(Mutex::new(CameraFrame::default())),
vertical_fov_radians: Arc::new(AtomicU32::new(60.0_f32.to_radians().to_bits())),
last_update: Mutex::new(LastUpdate::default()),
kinematics: RwLock::new(Kinematics::default()),
teleport: Mutex::new(TeleportState::default()),
@@ -986,7 +1014,11 @@ impl AgentMovementRuntime {
}
fn camera(&self, far: f32) -> AgentManagerAgentMovementAgentCamera {
AgentManagerAgentMovementAgentCamera::from_frame(Arc::clone(&self.camera_frame), far)
AgentManagerAgentMovementAgentCamera::from_frame(
Arc::clone(&self.camera_frame),
Arc::clone(&self.vertical_fov_radians),
far,
)
}
fn send_update(
@@ -2099,6 +2131,7 @@ impl AgentManagerAgentMovement {
}
pub fn set_fov_vertical_angle(&self, angle: f32) -> Result<(), Error> {
self.camera.set_vertical_fov_angle(angle)?;
let (agent_id, session_id) = self.runtime.ids();
let mut packet = AgentFOVPacket::new_with_constructor()?;
packet.agent_data.agent_id = agent_id;
@@ -3167,6 +3200,7 @@ mod tests {
assert!(run.agent_data.always_run);
manager.movement.set_fov_vertical_angle(1.25).unwrap();
assert_eq!(manager.movement.camera.vertical_fov_angle(), 1.25);
let fov = decode_packet::<AgentFOVPacket>(&grid.receive(PacketType::AgentFOV)).unwrap();
assert_eq!(fov.fov_block.vertical_angle, 1.25);