feo_oop_engine/scene/game_object/camera/
fpv_camera.rs1use {
6 super::{
7 Camera,
8 super::{
9 GameObject,
10 light::Light,
11 }
12 },
13 crate::{
14 registration::{
15 relation::{
16 Child, Parent,
17 ParentWrapper
18 },
19 named::Named,
20 id::ID
21 },
22 scripting::{
23 Script,
24 executor::Spawner,
25 Scriptable,
26 globals::{
27 EngineGlobals,
28 Global
29 }
30 },
31 components::{
32 triangle_mesh::TriangleMesh,
33 },
34 graphics::{
35 Drawable,
36 draw_pass_manager::DrawPassManager,
37 lighting_pass_manager::LightingPassManager,
38 },
39 event::UserEvent,
40 shaders::vs_draw,
41 },
42 feo_math::{
43 linear_algebra::{
44 vector3::Vector3,
45 matrix4::Matrix4
46 },
47 utils::space::Space,
48 rotation::quaternion::Quaternion
49 },
50 std::{
51 any::Any,
52 sync::{
53 Arc,
54 RwLock
55 },
56 mem
57 },
58 winit::event::Event,
59};
60
61#[derive(Scriptable, GameObject, Parent, Child, Named, Drawable)]
62#[camera]
63pub struct FpvCamera{
64 id: ID,
65 name: String,
66 parent: ParentWrapper,
67
68 main: bool,
69
70 offset: Option<Vector3<f32>>, fov: i32,
73 near_plane: f32,
74 far_plane: f32,
75 aspect_ratio: f32,
76
77 pub subspace: Space,
78
79 script: Option<Box<Script<Self>>>,
80
81 children: Vec<Arc<RwLock<dyn GameObject>>>,
82}
83
84impl std::fmt::Debug for FpvCamera {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 f.debug_struct("FpvCamera")
87 .field("id", &self.id)
88 .field("name", &self.name)
89 .field("parent", &self.parent)
90 .field("main", &self.main)
91 .field("offset", &self.offset)
92 .field("fov", &self.fov)
93 .field("near_plane", &self.near_plane)
94 .field("far_plane", &self.far_plane)
95 .field("aspect_ratio", &self.aspect_ratio)
96 .field("subspace", &self.subspace)
97 .field("script", &self.script)
98 .field("children", &self.children).finish()
99 }
100}
101
102impl Clone for FpvCamera {
103 fn clone(&self) -> Self {
104 let id = self.id.get_system().take();
105 FpvCamera{
106 id,
107 name: self.name.clone(),
108 parent: self.parent.clone(),
109 subspace: self.subspace,
110 script: self.script.clone(),
111 children: self.children.clone().into_iter().map(|_child| {
112 todo!();
114 }).collect::<Vec<Arc<RwLock<dyn GameObject>>>>(),
115 main: self.main,
116 offset: self.offset,
117 fov: self.fov,
118 near_plane: self.near_plane,
119 far_plane: self.far_plane,
120 aspect_ratio: self.aspect_ratio,
121 }
122 }
123}
124
125impl PartialEq for FpvCamera{
126 fn eq(&self, other: &Self) -> bool {
127 self.get_id() == other.get_id()
128 }
129}
130
131impl FpvCamera {
132 #[allow(clippy::too_many_arguments)]
133 pub fn new(
134 name: Option<&str>,
135
136 main: bool,
137
138 parent: Option<Arc<RwLock<dyn GameObject>>>, position: Option<Vector3<f32>>,
141 rotation: Option<Quaternion<f32>>,
142 scale_factor: Option<Vector3<f32>>,
143
144 offset: Option<Vector3<f32>>,
145
146 fov: i32,
147 near_plane: f32,
148 far_plane: f32,
149 aspect_ratio: f32,
150
151 script: Option<Box<Script<Self>>>,
152
153 engine_globals: EngineGlobals) -> Result<Arc<RwLock<Self>>, &'static str> { let id = engine_globals.id_system.take();
156 let subspace = Space::new(position, rotation, scale_factor);
157
158 Ok(Arc::new(RwLock::new( FpvCamera {
159 name: match name {
160 Some(name) => name.to_string(),
161 None => String::from("fpv_camera_") + id.to_string().as_str()
162 },
163 id,
164 parent: match parent {
165 Some(game_object) => {
166 ParentWrapper::GameObject(game_object)
167 },
168 None => {
169 ParentWrapper::Scene(engine_globals.scene)
170 }
171 },
172
173 main,
174 offset,
175 fov,
176 near_plane,
177 far_plane,
178 aspect_ratio,
179 subspace,
180
181 script,
182
183 children: Vec::new()
184 })))
185 }
186}
187
188impl Camera for FpvCamera {
189 fn as_any(&self) -> &dyn Any { self }
190 fn as_gameobject(&self) -> &dyn GameObject { self }
191
192 fn cast_gameobject_arc_rwlock(&self, this: Arc<RwLock<dyn Camera>>) -> Arc<RwLock<dyn GameObject>> {
193 let this= Arc::into_raw(this).cast::<RwLock<Self>>();
194 let this = unsafe { Arc::from_raw(this) };
195 this as Arc<RwLock<dyn GameObject>>
196 }
197
198 fn is_main(&self) -> bool {
199 self.main
200 }
201
202 fn get_z_step (&self, z_buffer_size: usize) -> f32 {
203 ((self.far_plane / self.near_plane) * 0.5).powi(z_buffer_size as i32)
204 }
205
206 fn build_projection(&self) -> Matrix4<f32> {
207 let half_h = self.near_plane * (self.fov as f32 * 0.5).tan();
208 let half_w = half_h * self.aspect_ratio;
209
210 Matrix4::new(
211 [ self.near_plane / half_w, 0.0, 0.0, 0.0],
212 [ 0.0, self.near_plane / -half_h, 0.0, 0.0],
213 [ 0.0, 0.0, -(self.near_plane + self.far_plane) / (self.far_plane - self.near_plane), (-2.0 * self.far_plane * self.near_plane) / (self.far_plane - self.near_plane)],
214 [ 0.0, 0.0, -1.0, 0.0]
215 )
216 }
217
218 fn build_viewspace(&self) -> Matrix4<f32> {
219 self.get_inversed_subspace().build()
220 }
221
222 fn create_uniforms(&self) -> vs_draw::ty::Camera {
223 vs_draw::ty::Camera {
224 to_view: self.build_viewspace().transpose().into(),
225 view_to_screen: self.build_projection().transpose().into()
226 }
227 }
228}