/
camera_control.rs
142 lines (132 loc) · 4.33 KB
/
camera_control.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use bevy::app::AppExit;
use bevy::pbr::DirectionalLightShadowMap;
use bevy::prelude::*;
use bevy_scene_hook::{HookPlugin, HookedSceneBundle, SceneHook};
use bevy_webcam_facial::*;
#[derive(Component)]
struct CameraControl;
#[derive(Component)]
struct CameraEye;
fn main() {
App::new()
.insert_resource(DirectionalLightShadowMap { size: 2048 })
.add_plugins(DefaultPlugins)
.add_plugins(WebcamFacialPlugin {
config_webcam_device: 0,
config_webcam_width: 640,
config_webcam_height: 480,
config_webcam_framerate: 33,
config_webcam_autostart: true,
// Using LowPass filter, with value of 'alpha' at 0.01 for last 20 frames to get more smoothing
config_filter_length: 20,
config_filter_type: SmoothingFilterType::LowPass(0.01),
})
// Using HookPlugin to get named object from loaded gltf scene
.add_plugins(HookPlugin)
.add_systems(Startup, load_scene)
.add_systems(
Update,
(
set_camera_position_from_plugin,
user_input_to_plugin_control_system,
),
)
.run();
}
/// set up 3D scene
fn load_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(HookedSceneBundle {
scene: SceneBundle {
scene: asset_server.load("rooster.gltf#Scene0"),
..default()
},
hook: SceneHook::new(|entity, cmds| {
match entity.get::<Name>().map(|t| t.as_str()) {
Some("Camera") => {
cmds.insert(CameraEye);
}
_ => {}
};
}),
});
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(0.0, 4.0, 0.0),
..default()
});
commands.spawn(
TextBundle::from_section(
"A: Start capture\nS: Stop capture\nESC: Exit app",
TextStyle {
font_size: 20.0,
color: Color::BLUE,
..default()
},
)
.with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(5.0),
left: Val::Px(15.0),
..default()
}),
);
}
fn set_camera_position_from_plugin(
mut camera: Query<&mut Transform, With<CameraEye>>,
mut webcam_data: EventReader<WebcamFacialDataEvent>,
_time: Res<Time>,
) {
for event in webcam_data.iter() {
let x = event.0.center_x;
let y = -event.0.center_y + 3.0;
for mut transform in camera.iter_mut() {
// For camera moving while looking at target:
transform.translation = Transform::from_xyz(x, y, 10.0)
.looking_at(
Vec3 {
x: 0.0,
y: 1.0,
z: 0.0,
},
Vec3::Y,
)
.translation;
transform.rotation = Transform::from_xyz(x, y, 10.0)
.looking_at(
Vec3 {
x: 0.0,
y: 1.0,
z: 0.0,
},
Vec3::Y,
)
.rotation;
/* OR */
// For FPS Mode (there is a better way to do this using bevy_fly_camera or bevy_orbit_controls or something else, plus easing/interpolation...):
// let pitch = y - 3.0;
// let yaw = -x;
// transform.rotation = Quat::from_axis_angle(Vec3::Y, yaw.to_radians() * 10.0)
// * Quat::from_axis_angle(-Vec3::X, pitch.to_radians() * 10.0);
}
}
}
// Keyboard control for plugin stop/start and app
fn user_input_to_plugin_control_system(
keyboard_input: Res<Input<KeyCode>>,
mut webcam_facial_control: ResMut<WebcamFacialController>,
mut exit: EventWriter<AppExit>,
) {
if keyboard_input.just_pressed(KeyCode::A) {
webcam_facial_control.control = true;
}
if keyboard_input.just_pressed(KeyCode::S) {
webcam_facial_control.control = false;
}
if keyboard_input.just_pressed(KeyCode::Escape) {
exit.send(AppExit);
}
}