bevy_orbit_camera/
transform.rs1use bevy::{ecs::prelude::*, math::prelude::*, reflect::Reflect, transform::components::Transform};
2
3#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect)]
5#[reflect(Component, Debug, PartialEq)]
6pub struct LookTransform {
7 pub eye: Vec3,
8 pub target: Vec3,
9 pub up: Vec3,
10}
11
12impl LookTransform {
13 pub fn new(eye: Vec3, target: Vec3, up: Vec3) -> Self {
14 Self { eye, target, up }
15 }
16
17 pub fn radius(&self) -> f32 {
18 (self.target - self.eye).length()
19 }
20}
21
22pub fn system(mut cameras: Query<(&LookTransform, &mut Transform), Changed<LookTransform>>) {
23 for (look_transform, mut scene_transform) in cameras.iter_mut() {
24 *scene_transform = (*look_transform).into();
25 }
26}
27
28impl From<LookTransform> for Transform {
29 fn from(t: LookTransform) -> Self {
30 let direction = (t.target - t.eye).try_normalize().unwrap_or(Vec3::NEG_Z);
31 let up = valid_up(t.up, direction);
32 Transform::from_translation(t.eye).looking_at(t.eye + direction, up)
33 }
34}
35
36fn valid_up(up: Vec3, direction: Vec3) -> Vec3 {
37 let up = up.try_normalize().unwrap_or(Vec3::Y);
38 if up.cross(direction).length_squared() > 1e-6 {
39 up
40 } else {
41 direction.any_orthonormal_vector()
42 }
43}