pub struct Quat(/* private fields */);Expand description
A quaternion representing an orientation.
This quaternion is intended to be of unit length but may denormalize due to floating point “error creep” which can occur when successive quaternion operations are applied.
SIMD vector types are used for storage on supported platforms.
This type is 16 byte aligned.
Implementations§
Source§impl Quat
impl Quat
Sourcepub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Quat
pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Quat
Creates a new rotation quaternion.
This should generally not be called manually unless you know what you are doing.
Use one of the other constructors instead such as identity or from_axis_angle.
from_xyzw is mostly used by unit tests and serde deserialization.
§Preconditions
This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.
Examples found in repository?
More examples
164const CAMERA_POSITIONS: &[Transform] = &[
165 Transform {
166 translation: Vec3::new(1.5, 1.5, 1.5),
167 rotation: Quat::from_xyzw(-0.279, 0.364, 0.115, 0.880),
168 scale: Vec3::ONE,
169 },
170 Transform {
171 translation: Vec3::new(2.4, 0.0, 0.2),
172 rotation: Quat::from_xyzw(0.094, 0.676, 0.116, 0.721),
173 scale: Vec3::ONE,
174 },
175 Transform {
176 translation: Vec3::new(2.4, 2.6, -4.3),
177 rotation: Quat::from_xyzw(0.170, 0.908, 0.308, 0.225),
178 scale: Vec3::ONE,
179 },
180 Transform {
181 translation: Vec3::new(-1.0, 0.8, -1.2),
182 rotation: Quat::from_xyzw(-0.004, 0.909, 0.247, -0.335),
183 scale: Vec3::ONE,
184 },
185];77fn setup_pica_pica(
78 mut commands: Commands,
79 asset_server: Res<AssetServer>,
80 args: Res<Args>,
81 #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] dlss_rr_supported: Option<
82 Res<DlssRayReconstructionSupported>,
83 >,
84) {
85 commands
86 .spawn((
87 WorldAssetRoot(
88 asset_server.load(
89 GltfAssetLabel::Scene(0)
90 .from_asset("https://github.com/bevyengine/bevy_asset_files/raw/2a5950295a8b6d9d051d59c0df69e87abcda58c3/pica_pica/mini_diorama_01.glb")
91 ),
92 ),
93 Transform::from_scale(Vec3::splat(10.0)),
94 ))
95 .observe(add_raytracing_meshes_on_scene_load);
96
97 commands
98 .spawn((
99 WorldAssetRoot(asset_server.load(
100 GltfAssetLabel::Scene(0).from_asset("https://github.com/bevyengine/bevy_asset_files/raw/2a5950295a8b6d9d051d59c0df69e87abcda58c3/pica_pica/robot_01.glb")
101 )),
102 Transform::from_scale(Vec3::splat(2.0))
103 .with_translation(Vec3::new(-2.0, 0.05, -2.1))
104 .with_rotation(Quat::from_rotation_y(PI / 2.0)),
105 PatrolPath {
106 path: vec![
107 (Vec3::new(-2.0, 0.05, -2.1), Quat::from_rotation_y(PI / 2.0)),
108 (Vec3::new(2.2, 0.05, -2.1), Quat::from_rotation_y(0.0)),
109 (
110 Vec3::new(2.2, 0.05, 2.1),
111 Quat::from_rotation_y(3.0 * PI / 2.0),
112 ),
113 (Vec3::new(-2.0, 0.05, 2.1), Quat::from_rotation_y(PI)),
114 ],
115 i: 0,
116 },
117 ))
118 .observe(add_raytracing_meshes_on_scene_load);
119
120 commands.spawn((
121 DirectionalLight {
122 illuminance: light_consts::lux::FULL_DAYLIGHT,
123 shadow_maps_enabled: false, // Solari replaces shadow mapping
124 ..default()
125 },
126 Transform::from_rotation(Quat::from_xyzw(
127 -0.13334629,
128 -0.86597735,
129 -0.3586996,
130 0.3219264,
131 )),
132 ));
133
134 let mut camera = commands.spawn((
135 Camera3d::default(),
136 Camera {
137 clear_color: ClearColorConfig::Custom(Color::BLACK),
138 ..default()
139 },
140 FreeCamera {
141 walk_speed: 3.0,
142 run_speed: 10.0,
143 ..Default::default()
144 },
145 Transform::from_translation(Vec3::new(0.219417, 2.5764852, 6.9718704)).with_rotation(
146 Quat::from_xyzw(-0.1466768, 0.013738206, 0.002037309, 0.989087),
147 ),
148 // Msaa::Off and CameraMainTextureUsages with STORAGE_BINDING are required for Solari
149 CameraMainTextureUsages::default().with(TextureUsages::STORAGE_BINDING),
150 Msaa::Off,
151 ));
152
153 if args.pathtracer == Some(true) {
154 camera.insert(Pathtracer::default());
155 } else {
156 camera.insert(SolariLighting::default());
157 }
158
159 // Using DLSS Ray Reconstruction for denoising (and cheaper rendering via upscaling) is _highly_ recommended when using Solari
160 #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
161 if dlss_rr_supported.is_some() {
162 camera.insert(Dlss::<DlssRayReconstructionFeature> {
163 perf_quality_mode: Default::default(),
164 reset: Default::default(),
165 _phantom_data: Default::default(),
166 });
167 }
168
169 commands.spawn((
170 ControlText,
171 Text::default(),
172 Node {
173 position_type: PositionType::Absolute,
174 bottom: px(12.0),
175 left: px(12.0),
176 ..default()
177 },
178 ));
179
180 commands.spawn((
181 Node {
182 position_type: PositionType::Absolute,
183 right: px(0.0),
184 padding: px(4.0).all(),
185 border_radius: BorderRadius::bottom_left(px(4.0)),
186 ..default()
187 },
188 BackgroundColor(Color::srgba(0.10, 0.10, 0.10, 0.8)),
189 children![(
190 PerformanceText,
191 Text::default(),
192 TextFont {
193 font_size: FontSize::Px(8.0),
194 ..default()
195 },
196 )],
197 ));
198}
199
200fn setup_many_lights(
201 mut commands: Commands,
202 asset_server: Res<AssetServer>,
203 mut meshes: ResMut<Assets<Mesh>>,
204 mut materials: ResMut<Assets<StandardMaterial>>,
205 args: Res<Args>,
206 #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))] dlss_rr_supported: Option<
207 Res<DlssRayReconstructionSupported>,
208 >,
209) {
210 let mut rng = ChaCha8Rng::seed_from_u64(42);
211
212 let mut plane_mesh = Plane3d::default()
213 .mesh()
214 .size(400.0, 400.0)
215 .build()
216 .with_generated_tangents()
217 .unwrap();
218 match plane_mesh.attribute_mut(Mesh::ATTRIBUTE_UV_0).unwrap() {
219 VertexAttributeValues::Float32x2(items) => {
220 items.iter_mut().flatten().for_each(|x| *x *= 3.0);
221 }
222 _ => unreachable!(),
223 }
224 let plane_mesh = meshes.add(plane_mesh);
225 let cube_mesh = meshes.add(
226 Cuboid::default()
227 .mesh()
228 .build()
229 .with_generated_tangents()
230 .unwrap(),
231 );
232 let sphere_mesh = meshes.add(
233 Sphere::new(1.0)
234 .mesh()
235 .build()
236 .with_generated_tangents()
237 .unwrap(),
238 );
239
240 commands
241 .spawn((
242 RaytracingMesh3d(plane_mesh.clone()),
243 MeshMaterial3d(
244 materials.add(StandardMaterial {
245 base_color_texture: Some(
246 asset_server
247 .load_builder()
248 .with_settings::<ImageLoaderSettings>(|settings| {
249 settings
250 .sampler
251 .get_or_init_descriptor()
252 .set_address_mode(ImageAddressMode::Repeat);
253 })
254 .load("textures/uv_checker_bw.png"),
255 ),
256 perceptual_roughness: 0.0,
257 ..default()
258 }),
259 ),
260 ))
261 .insert_if(Mesh3d(plane_mesh), || args.pathtracer != Some(true));
262
263 for _ in 0..8000 {
264 commands
265 .spawn((
266 RaytracingMesh3d(cube_mesh.clone()),
267 MeshMaterial3d(materials.add(StandardMaterial {
268 base_color: Color::srgb(rng.random(), rng.random(), rng.random()),
269 perceptual_roughness: rng.random(),
270 ..default()
271 })),
272 Transform::default()
273 .with_scale(Vec3 {
274 x: rng.random_range(0.2..=2.0),
275 y: rng.random_range(0.2..=2.0),
276 z: rng.random_range(0.2..=2.0),
277 })
278 .with_translation(Vec3::new(
279 rng.random_range(-180.0..=180.0),
280 0.2,
281 rng.random_range(-180.0..=180.0),
282 )),
283 ))
284 .insert_if(Mesh3d(cube_mesh.clone()), || args.pathtracer != Some(true));
285 }
286
287 for x in -10..=10 {
288 for y in -10..=10 {
289 commands
290 .spawn((
291 RaytracingMesh3d(sphere_mesh.clone()),
292 MeshMaterial3d(
293 materials.add(StandardMaterial {
294 emissive: Color::linear_rgb(
295 rng.random::<f32>() * 60000.0,
296 rng.random::<f32>() * 60000.0,
297 rng.random::<f32>() * 60000.0,
298 )
299 .into(),
300 ..default()
301 }),
302 ),
303 Transform::default().with_translation(Vec3::new(
304 (x * 20) as f32,
305 7.0,
306 (y * 20) as f32,
307 )),
308 ))
309 .insert_if(Mesh3d(sphere_mesh.clone()), || {
310 args.pathtracer != Some(true)
311 });
312 }
313 }
314
315 let mut camera = commands.spawn((
316 Camera3d::default(),
317 Camera {
318 clear_color: ClearColorConfig::Custom(Color::BLACK),
319 ..default()
320 },
321 FreeCamera {
322 walk_speed: 3.0,
323 run_speed: 10.0,
324 ..Default::default()
325 },
326 Transform::from_translation(Vec3::new(6.11329, 166.74896, 451.8226)).with_rotation(
327 Quat::from_xyzw(-0.183938, 0.009093744, 0.0017017953, 0.9828943),
328 ),
329 // Msaa::Off and CameraMainTextureUsages with STORAGE_BINDING are required for Solari
330 CameraMainTextureUsages::default().with(TextureUsages::STORAGE_BINDING),
331 Msaa::Off,
332 Bloom {
333 intensity: 0.1,
334 ..Bloom::NATURAL
335 },
336 ));
337
338 if args.pathtracer == Some(true) {
339 camera.insert(Pathtracer::default());
340 } else {
341 camera.insert(SolariLighting::default());
342 }
343
344 // Using DLSS Ray Reconstruction for denoising (and cheaper rendering via upscaling) is _highly_ recommended when using Solari
345 #[cfg(all(feature = "dlss", not(feature = "force_disable_dlss")))]
346 if dlss_rr_supported.is_some() {
347 camera.insert(Dlss::<DlssRayReconstructionFeature> {
348 perf_quality_mode: Default::default(),
349 reset: Default::default(),
350 _phantom_data: Default::default(),
351 });
352 }
353
354 commands.spawn((
355 Node {
356 position_type: PositionType::Absolute,
357 right: px(0.0),
358 padding: px(4.0).all(),
359 border_radius: BorderRadius::bottom_left(px(4.0)),
360 ..default()
361 },
362 BackgroundColor(Color::srgba(0.10, 0.10, 0.10, 0.8)),
363 children![(
364 PerformanceText,
365 Text::default(),
366 TextFont {
367 font_size: FontSize::Px(8.0),
368 ..default()
369 },
370 )],
371 ));
372}
373
374fn add_raytracing_meshes_on_scene_load(
375 scene_ready: On<WorldInstanceReady>,
376 children: Query<&Children>,
377 mesh_query: Query<(
378 &Mesh3d,
379 &MeshMaterial3d<StandardMaterial>,
380 Option<&GltfMaterialName>,
381 )>,
382 mut meshes: ResMut<Assets<Mesh>>,
383 mut materials: ResMut<Assets<StandardMaterial>>,
384 mut commands: Commands,
385 args: Res<Args>,
386) {
387 for descendant in children.iter_descendants(scene_ready.entity) {
388 if let Ok((Mesh3d(mesh_handle), MeshMaterial3d(material_handle), material_name)) =
389 mesh_query.get(descendant)
390 {
391 // Add raytracing mesh component
392 commands
393 .entity(descendant)
394 .insert(RaytracingMesh3d(mesh_handle.clone()));
395
396 // Ensure meshes are Solari compatible
397 let mut mesh = meshes.get_mut(mesh_handle).unwrap();
398 if !mesh.contains_attribute(Mesh::ATTRIBUTE_UV_0) {
399 let vertex_count = mesh.count_vertices();
400 mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0]; vertex_count]);
401 mesh.insert_attribute(
402 Mesh::ATTRIBUTE_TANGENT,
403 vec![[0.0, 0.0, 0.0, 0.0]; vertex_count],
404 );
405 }
406 if !mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT) {
407 mesh.generate_tangents().unwrap();
408 }
409 if mesh.contains_attribute(Mesh::ATTRIBUTE_UV_1) {
410 mesh.remove_attribute(Mesh::ATTRIBUTE_UV_1);
411 }
412 if let Some(indices) = mesh.indices_mut()
413 && let Indices::U16(_) = indices
414 {
415 *indices = Indices::U32(indices.iter().map(|i| i as u32).collect());
416 }
417
418 // Prevent rasterization if using pathtracer
419 if args.pathtracer == Some(true) {
420 commands.entity(descendant).remove::<Mesh3d>();
421 }
422
423 // Adjust scene materials to better demo Solari features
424 if material_name.map(|s| s.0.as_str()) == Some("material") {
425 let mut material = materials.get_mut(material_handle).unwrap();
426 material.emissive = LinearRgba::BLACK;
427 }
428 if material_name.map(|s| s.0.as_str()) == Some("Lights") {
429 let mut material = materials.get_mut(material_handle).unwrap();
430 material.emissive =
431 LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
432 material.alpha_mode = AlphaMode::Opaque;
433 material.specular_transmission = 0.0;
434
435 commands.insert_resource(RobotLightMaterial(material_handle.clone()));
436 }
437 if material_name.map(|s| s.0.as_str()) == Some("Glass_Dark_01") {
438 let mut material = materials.get_mut(material_handle).unwrap();
439 material.alpha_mode = AlphaMode::Opaque;
440 material.specular_transmission = 0.0;
441 }
442 }
443 }
444}
445
446fn pause_scene(mut time: ResMut<Time<Virtual>>, key_input: Res<ButtonInput<KeyCode>>) {
447 if key_input.just_pressed(KeyCode::Space) {
448 time.toggle();
449 }
450}
451
452#[derive(Resource)]
453struct RobotLightMaterial(Handle<StandardMaterial>);
454
455fn toggle_lights(
456 key_input: Res<ButtonInput<KeyCode>>,
457 robot_light_material: Option<Res<RobotLightMaterial>>,
458 mut materials: ResMut<Assets<StandardMaterial>>,
459 directional_light: Query<Entity, With<DirectionalLight>>,
460 mut commands: Commands,
461) {
462 if key_input.just_pressed(KeyCode::Digit1) {
463 if let Ok(directional_light) = directional_light.single() {
464 commands.entity(directional_light).despawn();
465 } else {
466 commands.spawn((
467 DirectionalLight {
468 illuminance: light_consts::lux::FULL_DAYLIGHT,
469 shadow_maps_enabled: false, // Solari replaces shadow mapping
470 ..default()
471 },
472 Transform::from_rotation(Quat::from_xyzw(
473 -0.13334629,
474 -0.86597735,
475 -0.3586996,
476 0.3219264,
477 )),
478 ));
479 }
480 }
481
482 if key_input.just_pressed(KeyCode::Digit2)
483 && let Some(robot_light_material) = robot_light_material
484 {
485 let mut material = materials.get_mut(&robot_light_material.0).unwrap();
486 if material.emissive == LinearRgba::BLACK {
487 material.emissive = LinearRgba::from(Color::srgb(0.941, 0.714, 0.043)) * 1_000_000.0;
488 } else {
489 material.emissive = LinearRgba::BLACK;
490 }
491 }
492}Sourcepub const fn from_array(a: [f32; 4]) -> Quat
pub const fn from_array(a: [f32; 4]) -> Quat
Creates a rotation quaternion from an array.
§Preconditions
This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.
Examples found in repository?
187fn spawn_light(commands: &mut Commands, app_status: &AppStatus) {
188 // Because this light can become a directional light, point light, or spot
189 // light depending on the settings, we add the union of the components
190 // necessary for this light to behave as all three of those.
191 commands
192 .spawn((
193 create_directional_light(app_status),
194 Transform::from_rotation(Quat::from_array([
195 0.6539259,
196 -0.34646285,
197 0.36505926,
198 -0.5648683,
199 ]))
200 .with_translation(vec3(57.693, 34.334, -6.422)),
201 ))
202 // These two are needed for point lights.
203 .insert(CubemapVisibleEntities::default())
204 .insert(CubemapFrusta::default())
205 // These two are needed for spot lights.
206 .insert(VisibleMeshEntities::default())
207 .insert(Frustum::default());
208}Sourcepub const fn from_vec4(v: Vec4) -> Quat
pub const fn from_vec4(v: Vec4) -> Quat
Creates a new rotation quaternion from a 4D vector.
§Preconditions
This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.
Sourcepub fn from_slice(slice: &[f32]) -> Quat
pub fn from_slice(slice: &[f32]) -> Quat
Sourcepub fn write_to_slice(self, slice: &mut [f32])
pub fn write_to_slice(self, slice: &mut [f32])
Sourcepub fn from_axis_angle(axis: Vec3, angle: f32) -> Quat
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Quat
Create a quaternion for a normalized rotation axis and angle (in radians).
The axis must be a unit vector.
§Panics
Will panic if axis is not normalized when glam_assert is enabled.
Examples found in repository?
More examples
181fn button_system(
182 interaction_query: Query<
183 (&Interaction, &ComputedUiTargetCamera, &RotateCamera),
184 (Changed<Interaction>, With<Button>),
185 >,
186 mut camera_query: Query<&mut Transform, With<Camera>>,
187) {
188 for (interaction, computed_target, RotateCamera(direction)) in &interaction_query {
189 if let Interaction::Pressed = *interaction {
190 // Since TargetCamera propagates to the children, we can use it to find
191 // which side of the screen the button is on.
192 if let Some(mut camera_transform) = computed_target
193 .get()
194 .and_then(|camera| camera_query.get_mut(camera).ok())
195 {
196 let angle = match direction {
197 Direction::Left => -0.1,
198 Direction::Right => 0.1,
199 };
200 camera_transform.rotate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, angle));
201 }
202 }
203 }
204}634fn move_camera(
635 keyboard_input: Res<ButtonInput<KeyCode>>,
636 mut mouse_wheel_reader: MessageReader<MouseWheel>,
637 mut cameras: Query<&mut Transform, With<Camera>>,
638) {
639 let (mut distance_delta, mut theta_delta) = (0.0, 0.0);
640
641 // Handle keyboard events.
642 if keyboard_input.pressed(KeyCode::KeyW) {
643 distance_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
644 }
645 if keyboard_input.pressed(KeyCode::KeyS) {
646 distance_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
647 }
648 if keyboard_input.pressed(KeyCode::KeyA) {
649 theta_delta += CAMERA_KEYBOARD_ORBIT_SPEED;
650 }
651 if keyboard_input.pressed(KeyCode::KeyD) {
652 theta_delta -= CAMERA_KEYBOARD_ORBIT_SPEED;
653 }
654
655 // Handle mouse events.
656 for mouse_wheel in mouse_wheel_reader.read() {
657 distance_delta -= mouse_wheel.y * CAMERA_MOUSE_WHEEL_ZOOM_SPEED;
658 }
659
660 // Update transforms.
661 for mut camera_transform in cameras.iter_mut() {
662 let local_z = camera_transform.local_z().as_vec3().normalize_or_zero();
663 if distance_delta != 0.0 {
664 camera_transform.translation = (camera_transform.translation.length() + distance_delta)
665 .clamp(CAMERA_ZOOM_RANGE.start, CAMERA_ZOOM_RANGE.end)
666 * local_z;
667 }
668 if theta_delta != 0.0 {
669 camera_transform
670 .translate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, theta_delta));
671 camera_transform.look_at(Vec3::ZERO, Vec3::Y);
672 }
673 }
674}20fn setup(
21 mut commands: Commands,
22 mut meshes: ResMut<Assets<Mesh>>,
23 mut standard_materials: ResMut<Assets<StandardMaterial>>,
24 mut decal_standard_materials: ResMut<Assets<ForwardDecalMaterial<StandardMaterial>>>,
25 asset_server: Res<AssetServer>,
26) {
27 // Spawn the forward decal
28 commands.spawn((
29 Name::new("Decal"),
30 ForwardDecal,
31 MeshMaterial3d(decal_standard_materials.add(ForwardDecalMaterial {
32 base: StandardMaterial {
33 base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
34 ..default()
35 },
36 extension: ForwardDecalMaterialExt {
37 depth_fade_factor: 1.0,
38 },
39 })),
40 Transform::from_scale(Vec3::splat(4.0)),
41 ));
42
43 commands.spawn((
44 Name::new("Camera"),
45 Camera3d::default(),
46 FreeCamera::default(),
47 // Must enable the depth prepass to render forward decals
48 DepthPrepass,
49 Transform::from_xyz(2.0, 9.5, 2.5).looking_at(Vec3::ZERO, Vec3::Y),
50 ));
51
52 let white_material = standard_materials.add(Color::WHITE);
53
54 commands.spawn((
55 Name::new("Floor"),
56 Mesh3d(meshes.add(Rectangle::from_length(10.0))),
57 MeshMaterial3d(white_material.clone()),
58 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
59 ));
60
61 // Spawn a few cube with random rotations to showcase how the decals behave with non-flat geometry
62 let num_obs = 10;
63 let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
64 for i in 0..num_obs {
65 for j in 0..num_obs {
66 let rotation_axis: [f32; 3] = rng.random();
67 let rotation_vec: Vec3 = rotation_axis.into();
68 let rotation: u32 = rng.random_range(0..360);
69 let transform = Transform::from_xyz(
70 (-num_obs + 1) as f32 / 2.0 + i as f32,
71 -0.2,
72 (-num_obs + 1) as f32 / 2.0 + j as f32,
73 )
74 .with_rotation(Quat::from_axis_angle(
75 rotation_vec.normalize_or_zero(),
76 (rotation as f32).to_radians(),
77 ));
78
79 commands.spawn((
80 Mesh3d(meshes.add(Cuboid::from_length(0.6))),
81 MeshMaterial3d(white_material.clone()),
82 transform,
83 ));
84 }
85 }
86
87 commands.spawn((
88 Name::new("Light"),
89 PointLight {
90 shadow_maps_enabled: true,
91 ..default()
92 },
93 Transform::from_xyz(4.0, 8.0, 4.0),
94 ));
95}109fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
110 commands.spawn((
111 Camera3d::default(),
112 Transform::from_xyz(-0.8, 0.6, -0.8).looking_at(Vec3::new(0.0, 0.35, 0.0), Vec3::Y),
113 ContactShadows::default(),
114 TemporalAntiAliasing::default(), // Contact shadows and AO benefit from TAA
115 // Everything past this point is extra to look pretty.
116 Bloom::default(),
117 Hdr,
118 Skybox {
119 brightness: 1000.0,
120 image: Some(asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2")),
121 ..default()
122 },
123 EnvironmentMapLight {
124 diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
125 specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
126 intensity: 1000.0,
127 ..default()
128 },
129 ScreenSpaceAmbientOcclusion::default(),
130 Msaa::Off,
131 Tonemapping::AcesFitted,
132 MotionBlur {
133 shutter_angle: 2.0, // This is really just for fun when spinning the model
134 ..default()
135 },
136 ));
137
138 let directional_light = commands
139 .spawn((
140 DirectionalLight {
141 shadow_maps_enabled: true,
142 contact_shadows_enabled: true,
143 ..default()
144 },
145 Visibility::Hidden,
146 ))
147 .id();
148
149 let point_light = commands
150 .spawn((
151 PointLight {
152 intensity: light_consts::lumens::VERY_LARGE_CINEMA_LIGHT * 0.4,
153 shadow_maps_enabled: true,
154 contact_shadows_enabled: true,
155 ..default()
156 },
157 Visibility::Visible,
158 ))
159 .id();
160
161 let spot_light = commands
162 .spawn((
163 SpotLight {
164 intensity: light_consts::lumens::VERY_LARGE_CINEMA_LIGHT * 0.4,
165 shadow_maps_enabled: true,
166 contact_shadows_enabled: true,
167 ..default()
168 },
169 Visibility::Hidden,
170 ))
171 .id();
172
173 commands
174 .spawn((
175 Transform::from_xyz(-0.8, 1.5, 1.2).looking_at(Vec3::ZERO, Vec3::Y),
176 Visibility::default(),
177 LightContainer,
178 ))
179 .add_child(directional_light)
180 .add_child(point_light)
181 .add_child(spot_light);
182
183 commands
184 .spawn((
185 WorldAssetRoot(asset_server.load(
186 GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"),
187 )),
188 Transform::from_rotation(Quat::from_rotation_y(std::f32::consts::PI)),
189 ))
190 .observe(
191 |event: On<Pointer<Drag>>,
192 mut query: Query<&mut Transform, With<WorldAssetRoot>>,
193 mut commands: Commands,
194 mut window: Query<Entity, With<PrimaryWindow>>| {
195 for mut transform in query.iter_mut() {
196 transform.rotate_y(event.delta.x * 0.01);
197 }
198 commands
199 .entity(window.single_mut().unwrap())
200 .insert(CursorIcon::System(SystemCursorIcon::Grabbing));
201 },
202 )
203 .observe(
204 |_: On<Pointer<Over>>,
205 mut commands: Commands,
206 mut window: Query<Entity, With<PrimaryWindow>>| {
207 commands
208 .entity(window.single_mut().unwrap())
209 .insert(CursorIcon::System(SystemCursorIcon::Grab));
210 },
211 )
212 .observe(
213 |_: On<Pointer<Out>>,
214 mut commands: Commands,
215 mut window: Query<Entity, With<PrimaryWindow>>| {
216 commands
217 .entity(window.single_mut().unwrap())
218 .insert(CursorIcon::System(SystemCursorIcon::Default));
219 },
220 )
221 .observe(
222 |_: On<Pointer<DragEnd>>,
223 mut commands: Commands,
224 mut window: Query<Entity, With<PrimaryWindow>>| {
225 commands
226 .entity(window.single_mut().unwrap())
227 .insert(CursorIcon::System(SystemCursorIcon::Default));
228 },
229 );
230
231 commands.spawn((
232 Mesh3d(asset_server.add(Circle::default().mesh().into())),
233 MeshMaterial3d(asset_server.add(StandardMaterial {
234 base_color: Color::srgb(0.06, 0.06, 0.06),
235 ..default()
236 })),
237 Transform::from_rotation(Quat::from_axis_angle(Vec3::X, -std::f32::consts::FRAC_PI_2)),
238 GroundPlane,
239 ));
240
241 spawn_buttons(&mut commands);
242
243 commands.spawn((
244 Node {
245 position_type: PositionType::Absolute,
246 top: px(12.0),
247 left: px(0.0),
248 right: px(0.0),
249 justify_content: JustifyContent::Center,
250 ..default()
251 },
252 children![(
253 Text::new("Drag model to spin"),
254 TextFont {
255 font_size: FontSize::Px(18.0),
256 ..default()
257 },
258 )],
259 ));
260}Sourcepub fn from_scaled_axis(v: Vec3) -> Quat
pub fn from_scaled_axis(v: Vec3) -> Quat
Create a quaternion that rotates v.length() radians around v.normalize().
from_scaled_axis(Vec3::ZERO) results in the identity quaternion.
Examples found in repository?
71fn setup(
72 mut commands: Commands,
73 mut meshes: ResMut<Assets<Mesh>>,
74 mut materials: ResMut<Assets<StandardMaterial>>,
75) {
76 // Make a box of planes facing inward so the laser gets trapped inside
77 let plane_mesh = meshes.add(Plane3d::default());
78 let plane_material = materials.add(Color::from(css::GRAY).with_alpha(0.01));
79 let create_plane = move |translation, rotation| {
80 (
81 Transform::from_translation(translation)
82 .with_rotation(Quat::from_scaled_axis(rotation)),
83 Mesh3d(plane_mesh.clone()),
84 MeshMaterial3d(plane_material.clone()),
85 )
86 };
87
88 commands.spawn(create_plane(vec3(0.0, 0.5, 0.0), Vec3::X * PI));
89 commands.spawn(create_plane(vec3(0.0, -0.5, 0.0), Vec3::ZERO));
90 commands.spawn(create_plane(vec3(0.5, 0.0, 0.0), Vec3::Z * FRAC_PI_2));
91 commands.spawn(create_plane(vec3(-0.5, 0.0, 0.0), Vec3::Z * -FRAC_PI_2));
92 commands.spawn(create_plane(vec3(0.0, 0.0, 0.5), Vec3::X * -FRAC_PI_2));
93 commands.spawn(create_plane(vec3(0.0, 0.0, -0.5), Vec3::X * FRAC_PI_2));
94
95 // Light
96 commands.spawn((
97 DirectionalLight::default(),
98 Transform::from_rotation(Quat::from_euler(EulerRot::XYZ, -0.1, 0.2, 0.0)),
99 ));
100
101 // Camera
102 commands.spawn((
103 Camera3d::default(),
104 Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::ZERO, Vec3::Y),
105 Tonemapping::TonyMcMapface,
106 Bloom::default(),
107 ));
108}Sourcepub fn from_rotation_x(angle: f32) -> Quat
pub fn from_rotation_x(angle: f32) -> Quat
Creates a quaternion from the angle (in radians) around the x axis.
Examples found in repository?
220fn spawn_ground_plane(
221 commands: &mut Commands,
222 meshes: &mut Assets<Mesh>,
223 standard_materials: &mut Assets<StandardMaterial>,
224) {
225 commands.spawn((
226 Mesh3d(meshes.add(Circle::new(200.0))),
227 MeshMaterial3d(standard_materials.add(Color::from(GREEN))),
228 Transform::from_rotation(Quat::from_rotation_x(-FRAC_PI_2))
229 .with_translation(vec3(-25.0, 0.0, 0.0)),
230 ));
231}
232
233/// Creates the initial image that the mirror camera will render the mirror
234/// world to.
235fn create_mirror_texture_resource(
236 commands: &mut Commands,
237 windows_query: &Query<&Window>,
238 images: &mut Assets<Image>,
239) -> Handle<Image> {
240 let window = windows_query.iter().next().expect("No window found");
241 let window_size = uvec2(window.physical_width(), window.physical_height());
242 let image = create_mirror_texture_image(images, window_size);
243 commands.insert_resource(MirrorImage(image.clone()));
244 image
245}
246
247/// Spawns the camera that renders the mirror world.
248fn spawn_mirror_camera(
249 commands: &mut Commands,
250 camera_transform: &Transform,
251 camera_projection: &PerspectiveProjection,
252 mirror_transform: &Transform,
253 mirror_render_target: Handle<Image>,
254) {
255 let (mirror_camera_transform, mirror_camera_projection) =
256 calculate_mirror_camera_transform_and_projection(
257 camera_transform,
258 camera_projection,
259 mirror_transform,
260 );
261
262 commands.spawn((
263 Camera3d::default(),
264 Camera {
265 order: -1,
266 // Reflecting the model across the mirror will flip the winding of
267 // all the polygons. Therefore, in order to properly backface cull,
268 // we need to turn on `invert_culling`.
269 invert_culling: true,
270 ..default()
271 },
272 RenderTarget::Image(mirror_render_target.clone().into()),
273 mirror_camera_transform,
274 Projection::Perspective(mirror_camera_projection),
275 MirrorCamera,
276 ));
277}
278
279/// Spawns the animated fox.
280///
281/// Note that this doesn't play the animation; that's handled in
282/// [`play_fox_animation`].
283fn spawn_fox(commands: &mut Commands, asset_server: &AssetServer) {
284 commands.spawn((
285 WorldAssetRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_ASSET_PATH))),
286 Transform::from_xyz(-50.0, 0.0, -100.0),
287 ));
288}
289
290/// Spawns the mirror plane mesh and returns its transform.
291fn spawn_mirror(
292 commands: &mut Commands,
293 meshes: &mut Assets<Mesh>,
294 screen_space_texture_materials: &mut Assets<
295 ExtendedMaterial<StandardMaterial, ScreenSpaceTextureExtension>,
296 >,
297 mirror_render_target: Handle<Image>,
298) -> Transform {
299 let mirror_transform = Transform::from_scale(vec3(300.0, 1.0, 150.0))
300 .with_rotation(Quat::from_rotation_x(MIRROR_ROTATION_ANGLE))
301 .with_translation(MIRROR_POSITION);
302
303 commands.spawn((
304 Mesh3d(meshes.add(Plane3d::default().mesh().size(1.0, 1.0))),
305 MeshMaterial3d(screen_space_texture_materials.add(ExtendedMaterial {
306 base: StandardMaterial {
307 base_color: Color::BLACK,
308 emissive: Color::WHITE.into(),
309 emissive_texture: Some(mirror_render_target),
310 perceptual_roughness: 0.0,
311 metallic: 1.0,
312 ..default()
313 },
314 extension: ScreenSpaceTextureExtension { dummy: 0.0 },
315 })),
316 mirror_transform,
317 Mirror,
318 ));
319
320 mirror_transform
321}More examples
357fn draw_gizmos(mut gizmos: Gizmos, spotlight: Query<(&GlobalTransform, &SpotLight, &Visibility)>) {
358 if let Ok((global_transform, spotlight, visibility)) = spotlight.single()
359 && visibility != Visibility::Hidden
360 {
361 gizmos.primitive_3d(
362 &Cone::new(7.0 * spotlight.outer_angle, 7.0),
363 Isometry3d {
364 rotation: global_transform.rotation() * Quat::from_rotation_x(FRAC_PI_2),
365 translation: global_transform.translation_vec3a() * 0.5,
366 },
367 YELLOW,
368 );
369 }
370}130fn spawn_test_scene(
131 mut commands: Commands,
132 mut meshes: ResMut<Assets<Mesh>>,
133 mut materials: ResMut<Assets<StandardMaterial>>,
134) {
135 commands.spawn((
136 Mesh3d(meshes.add(Circle::new(4.0))),
137 MeshMaterial3d(materials.add(Color::WHITE)),
138 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
139 ));
140 commands.spawn((
141 Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
142 MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
143 Transform::from_xyz(0.0, 1.0, 0.0),
144 ));
145 commands.spawn((
146 PointLight {
147 shadow_maps_enabled: true,
148 ..default()
149 },
150 Transform::from_xyz(4.0, 8.0, 4.0),
151 ));
152}346fn draw_camera_gizmo(cameras: Query<(&Camera, &GlobalTransform)>, mut gizmos: Gizmos) {
347 for (camera, transform) in &cameras {
348 // As above, we use the order as a cheap tag to tell the depth texture
349 // apart from the main texture.
350 if camera.order >= 0 {
351 continue;
352 }
353
354 // Draw a cone representing the camera.
355 gizmos.primitive_3d(
356 &Cone {
357 radius: 1.0,
358 height: 3.0,
359 },
360 Isometry3d::new(
361 transform.translation(),
362 // We have to rotate here because `Cone` primitives are oriented
363 // along +Y and cameras point along +Z.
364 transform.rotation() * Quat::from_rotation_x(FRAC_PI_2),
365 ),
366 LIME,
367 );
368 }
369}131fn setup_env(
132 mut commands: Commands,
133 mut meshes: ResMut<Assets<Mesh>>,
134 mut materials: ResMut<Assets<StandardMaterial>>,
135) {
136 // Spawn a circular ground plane
137 commands.spawn((
138 Mesh3d(meshes.add(Circle::new(1.618 * NUM_CUBES as f32))),
139 MeshMaterial3d(materials.add(Color::WHITE)),
140 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
141 ));
142
143 // Spawn a point light with shadows enabled
144 commands.spawn((
145 PointLight {
146 shadow_maps_enabled: true,
147 ..default()
148 },
149 Transform::from_xyz(0.0, LIGHT_RADIUS, 4.0),
150 ));
151
152 // Spawn a camera looking at the origin
153 commands.spawn((
154 Camera3d::default(),
155 Transform::from_xyz(-6.5, 5.5, 12.0).looking_at(Vec3::ZERO, Vec3::Y),
156 ));
157}13fn scene() -> impl SceneList {
14 bsn_list! [
15 (
16 #CircularBase
17 Mesh3d(asset_value(Circle::new(4.0)))
18 MeshMaterial3d::<StandardMaterial>(asset_value(Color::WHITE))
19 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2))
20 ),
21 (
22 #Cube
23 Mesh3d(asset_value(Cuboid::new(1.0, 1.0, 1.0)))
24 MeshMaterial3d::<StandardMaterial>(asset_value(Color::srgb_u8(124, 144, 255)))
25 Transform::from_xyz(0.0, 0.5, 0.0)
26 ),
27 (
28 PointLight {
29 shadow_maps_enabled: true,
30 }
31 Transform::from_xyz(4.0, 8.0, 4.0)
32 ),
33 (
34 Camera3d
35 template_value(Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y))
36 )
37 ]
38}- examples/animation/animation_graph.rs
- tests/3d/test_skinned_mesh_bounds.rs
- examples/remote/server.rs
- examples/animation/animation_masks.rs
- examples/camera/custom_projection.rs
- examples/diagnostics/log_diagnostics.rs
- examples/shader_advanced/custom_render_phase.rs
- examples/3d/skybox.rs
- examples/3d/light_probe_blending.rs
- examples/picking/simple_picking.rs
- examples/asset/generated_assets.rs
- examples/picking/debug_picking.rs
- examples/animation/custom_skinned_mesh.rs
- examples/camera/free_camera_controller.rs
- examples/app/headless_renderer.rs
- examples/app/render_recovery.rs
- examples/3d/specular_tint.rs
- examples/stress_tests/many_cameras_lights.rs
- examples/3d/texture.rs
- examples/3d/decal.rs
- examples/testbed/3d.rs
- examples/shader_advanced/compute_mesh.rs
- examples/3d/render_to_texture.rs
- examples/gizmos/3d_gizmos.rs
- examples/math/custom_primitives.rs
- examples/gizmos/light_gizmos.rs
- examples/picking/mesh_picking.rs
- examples/ui/render_ui_to_texture.rs
- examples/3d/3d_shapes.rs
- examples/usage/debug_frustum_culling.rs
- examples/3d/lighting.rs
Sourcepub fn from_rotation_y(angle: f32) -> Quat
pub fn from_rotation_y(angle: f32) -> Quat
Creates a quaternion from the angle (in radians) around the y axis.
Examples found in repository?
More examples
- examples/3d/fog_volumes.rs
- examples/3d/rotate_environment_map.rs
- examples/3d/spotlight.rs
- examples/3d/anisotropy.rs
- examples/shader/shader_material_wesl.rs
- examples/gizmos/3d_text_gizmos.rs
- examples/transforms/scale.rs
- examples/transforms/align.rs
- examples/math/random_sampling.rs
- examples/3d/post_processing.rs
- examples/3d/color_grading.rs
- tests/3d/test_skinned_mesh_bounds.rs
- examples/3d/tonemapping.rs
- examples/3d/atmosphere.rs
- examples/transforms/transform.rs
- examples/animation/custom_skinned_mesh.rs
- examples/3d/auto_exposure.rs
- examples/3d/order_independent_transparency.rs
- examples/3d/rect_light.rs
- examples/animation/eased_motion.rs
- examples/3d/blend_modes.rs
- examples/showcase/alien_cake_addict.rs
- examples/gizmos/3d_gizmos.rs
- examples/3d/meshlet.rs
- examples/3d/solari.rs
- examples/stress_tests/many_foxes.rs
- examples/3d/contact_shadows.rs
Sourcepub fn from_rotation_z(angle: f32) -> Quat
pub fn from_rotation_z(angle: f32) -> Quat
Creates a quaternion from the angle (in radians) around the z axis.
Examples found in repository?
More examples
- examples/ecs/fallible_params.rs
- examples/animation/morph_targets.rs
- examples/2d/rotate_to_cursor.rs
- tests/3d/test_skinned_mesh_bounds.rs
- examples/gltf/gltf_skinned_mesh.rs
- examples/stress_tests/many_sprites.rs
- examples/stress_tests/many_sprite_meshes.rs
- examples/testbed/2d.rs
- examples/stress_tests/many_morph_targets.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/stress_tests/many_animated_sprite_meshes.rs
- examples/animation/custom_skinned_mesh.rs
- examples/stress_tests/many_text2d.rs
- examples/3d/motion_blur.rs
- examples/picking/sprite_picking.rs
- examples/2d/mesh2d_arcs.rs
- examples/usage/debug_frustum_culling.rs
Sourcepub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Quat
pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Quat
Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
Examples found in repository?
More examples
343fn spin_large_cube(mut large_cubes: Query<&mut Transform, With<LargeCube>>) {
344 for mut transform in &mut large_cubes {
345 transform.rotate(Quat::from_euler(
346 EulerRot::XYZ,
347 0.13 * ROTATION_SPEED,
348 0.29 * ROTATION_SPEED,
349 0.35 * ROTATION_SPEED,
350 ));
351 }
352}
353
354/// Spawns a directional light to illuminate the scene.
355fn spawn_light(commands: &mut Commands) {
356 commands
357 .spawn(DirectionalLight::default())
358 .insert(Transform::from_rotation(Quat::from_euler(
359 EulerRot::ZYX,
360 0.0,
361 PI * -0.15,
362 PI * -0.15,
363 )));
364}51fn animate_light_direction(
52 time: Res<Time>,
53 mut query: Query<&mut Transform, With<DirectionalLight>>,
54) {
55 for mut transform in &mut query {
56 transform.rotation = Quat::from_euler(
57 EulerRot::ZYX,
58 0.0,
59 time.elapsed_secs() * PI / 5.0,
60 -FRAC_PI_4,
61 );
62 }
63}54fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
55 commands.spawn((
56 Camera3d::default(),
57 Transform::from_xyz(4.0, 4.0, 12.0).looking_at(Vec3::new(0.0, 0.0, 0.5), Vec3::Y),
58 ));
59
60 commands.spawn((
61 Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
62 DirectionalLight::default(),
63 ));
64
65 commands.spawn(WorldAssetRoot(asset_server.load(
66 GltfAssetLabel::Scene(0).from_asset("models/GltfPrimitives/gltf_primitives.glb"),
67 )));
68}137fn light_sway(time: Res<Time>, mut query: Query<(&mut Transform, &mut SpotLight)>) {
138 for (mut transform, mut angles) in query.iter_mut() {
139 transform.rotation = Quat::from_euler(
140 EulerRot::XYZ,
141 -FRAC_PI_2 + ops::sin(time.elapsed_secs() * 0.67 * 3.0) * 0.5,
142 ops::sin(time.elapsed_secs() * 3.0) * 0.5,
143 0.0,
144 );
145 let angle = (ops::sin(time.elapsed_secs() * 1.2) + 1.0) * (FRAC_PI_4 - 0.1);
146 angles.inner_angle = angle * 0.8;
147 angles.outer_angle = angle;
148 }
149}188fn setup_scene(
189 mut commands: Commands,
190 mut meshes: ResMut<Assets<Mesh>>,
191 mut materials: ResMut<Assets<StandardMaterial>>,
192) {
193 // Camera
194 commands.spawn((
195 Camera3d::default(),
196 Transform::from_xyz(10.0, 10.0, 15.0).looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
197 ));
198
199 // Light
200 commands.spawn((
201 DirectionalLight {
202 shadow_maps_enabled: true,
203 ..default()
204 },
205 Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
206 ));
207
208 // Plane
209 commands.spawn((
210 Mesh3d(meshes.add(Plane3d::default().mesh().size(50000.0, 50000.0))),
211 MeshMaterial3d(materials.add(Color::srgb(0.7, 0.2, 0.2))),
212 Loading,
213 ));
214}- examples/animation/animated_mesh.rs
- examples/3d/volumetric_fog.rs
- examples/3d/post_processing.rs
- examples/3d/color_grading.rs
- examples/3d/pcss.rs
- examples/3d/tonemapping.rs
- examples/stress_tests/many_materials.rs
- examples/testbed/3d.rs
- examples/gltf/gltf_extension_animation_graph.rs
- examples/3d/mesh_ray_cast.rs
- examples/animation/animated_mesh_control.rs
- examples/movement/physics_in_fixed_timestep.rs
- examples/camera/free_camera_controller.rs
- examples/camera/camera_orbit.rs
- examples/3d/ssao.rs
- examples/animation/animated_mesh_events.rs
- examples/3d/clustered_decals.rs
- examples/camera/first_person_view_model.rs
- examples/3d/mirror.rs
- examples/3d/light_textures.rs
- examples/3d/visibility_range.rs
- examples/3d/shadow_caster_receiver.rs
- examples/3d/anti_aliasing.rs
- examples/gizmos/transform_gizmo.rs
- examples/3d/meshlet.rs
- examples/3d/split_screen.rs
- examples/stress_tests/many_foxes.rs
- examples/3d/deferred_rendering.rs
- examples/3d/transmission.rs
Sourcepub fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Quat
pub fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Quat
From the columns of a 3x3 rotation matrix.
Note if the input axes contain scales, shears, or other non-rotation transformations then the output of this function is ill-defined.
§Panics
Will panic if any axis is not normalized when glam_assert is enabled.
Sourcepub fn from_mat3(mat: &Mat3) -> Quat
pub fn from_mat3(mat: &Mat3) -> Quat
Creates a quaternion from a 3x3 rotation matrix.
Note if the input matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.
§Panics
Will panic if any input matrix column is not normalized when glam_assert is enabled.
Examples found in repository?
632fn rotate_primitive_2d_meshes(
633 mut primitives_2d: Query<
634 (&mut Transform, &ViewVisibility),
635 (With<PrimitiveData>, With<MeshDim2>),
636 >,
637 time: Res<Time>,
638) {
639 let rotation_2d = Quat::from_mat3(&Mat3::from_angle(time.elapsed_secs()));
640 primitives_2d
641 .iter_mut()
642 .filter(|(_, vis)| vis.get())
643 .for_each(|(mut transform, _)| {
644 transform.rotation = rotation_2d;
645 });
646}More examples
136fn track_targets(
137 // `Single` ensures the system runs ONLY when exactly one matching entity exists.
138 mut player: Single<(&mut Transform, &Player)>,
139 // `Option<Single>` never prevents the system from running, but will be `None` if there is not exactly one matching entity.
140 enemy: Option<Single<&Transform, (With<Enemy>, Without<Player>)>>,
141 time: Res<Time>,
142) {
143 let (player_transform, player) = &mut *player;
144 if let Some(enemy_transform) = enemy {
145 // Enemy found, rotate and move towards it.
146 let delta = enemy_transform.translation - player_transform.translation;
147 let distance = delta.length();
148 let front = delta / distance;
149 let up = Vec3::Z;
150 let side = front.cross(up);
151 player_transform.rotation = Quat::from_mat3(&Mat3::from_cols(side, front, up));
152 let max_step = distance - player.min_follow_radius;
153 if 0.0 < max_step {
154 let velocity = (player.speed * time.delta_secs()).min(max_step);
155 player_transform.translation += front * velocity;
156 }
157 } else {
158 // 0 or multiple enemies found, keep searching.
159 player_transform.rotate_axis(Dir3::Z, player.rotation_speed * time.delta_secs());
160 }
161}Sourcepub fn from_mat3a(mat: &Mat3A) -> Quat
pub fn from_mat3a(mat: &Mat3A) -> Quat
Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
Note if the input matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.
§Panics
Will panic if any input matrix column is not normalized when glam_assert is enabled.
Sourcepub fn from_mat4(mat: &Mat4) -> Quat
pub fn from_mat4(mat: &Mat4) -> Quat
Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.
Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.
§Panics
Will panic if any column of the upper 3x3 rotation matrix is not normalized when
glam_assert is enabled.
Sourcepub fn from_rotation_arc(from: Vec3, to: Vec3) -> Quat
pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Quat
Gets the minimal rotation for transforming from to to. The rotation is in the
plane spanned by the two vectors. Will rotate at most 180 degrees.
The inputs must be unit vectors.
from_rotation_arc(from, to) * from ≈ to.
For near-singular cases (from≈to and from≈-to) the current implementation
is only accurate to about 0.001 (for f32).
§Panics
Will panic if from or to are not normalized when glam_assert is enabled.
Examples found in repository?
648fn rotate_primitive_3d_meshes(
649 mut primitives_3d: Query<
650 (&mut Transform, &ViewVisibility),
651 (With<PrimitiveData>, With<MeshDim3>),
652 >,
653 time: Res<Time>,
654) {
655 let rotation_3d = Quat::from_rotation_arc(
656 Vec3::Z,
657 Vec3::new(
658 ops::sin(time.elapsed_secs()),
659 ops::cos(time.elapsed_secs()),
660 ops::sin(time.elapsed_secs()) * 0.5,
661 )
662 .try_normalize()
663 .unwrap_or(Vec3::Z),
664 );
665 primitives_3d
666 .iter_mut()
667 .filter(|(_, vis)| vis.get())
668 .for_each(|(mut transform, _)| {
669 transform.rotation = rotation_3d;
670 });
671}
672
673fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
674 const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
675 let rotation = Quat::from_rotation_arc(
676 Vec3::Z,
677 Vec3::new(
678 ops::sin(time.elapsed_secs()),
679 ops::cos(time.elapsed_secs()),
680 ops::sin(time.elapsed_secs()) * 0.5,
681 )
682 .try_normalize()
683 .unwrap_or(Vec3::Z),
684 );
685 let isometry = Isometry3d::new(POSITION, rotation);
686 let color = Color::WHITE;
687 let resolution = 10;
688
689 #[expect(
690 clippy::match_same_arms,
691 reason = "Certain primitives don't have any 3D rendering support yet."
692 )]
693 match state.get() {
694 PrimitiveSelected::RectangleAndCuboid => {
695 gizmos.primitive_3d(&CUBOID, isometry, color);
696 }
697 PrimitiveSelected::CircleAndSphere => drop(
698 gizmos
699 .primitive_3d(&SPHERE, isometry, color)
700 .resolution(resolution),
701 ),
702 PrimitiveSelected::Ellipse => {}
703 PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, isometry, color),
704 PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, isometry, color)),
705 PrimitiveSelected::Line => gizmos.primitive_3d(&LINE_3D, isometry, color),
706 PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, isometry, color),
707 PrimitiveSelected::Polyline => gizmos.primitive_3d(
708 &Polyline3d {
709 vertices: POLYLINE_3D_VERTICES.to_vec(),
710 },
711 isometry,
712 color,
713 ),
714 PrimitiveSelected::Polygon => {}
715 PrimitiveSelected::ConvexPolygon => {}
716 PrimitiveSelected::RegularPolygon => {}
717 PrimitiveSelected::Capsule => drop(
718 gizmos
719 .primitive_3d(&CAPSULE_3D, isometry, color)
720 .resolution(resolution),
721 ),
722 PrimitiveSelected::Cylinder => drop(
723 gizmos
724 .primitive_3d(&CYLINDER, isometry, color)
725 .resolution(resolution),
726 ),
727 PrimitiveSelected::Cone => drop(
728 gizmos
729 .primitive_3d(&CONE, isometry, color)
730 .resolution(resolution),
731 ),
732 PrimitiveSelected::ConicalFrustum => {
733 gizmos.primitive_3d(&CONICAL_FRUSTUM, isometry, color);
734 }
735
736 PrimitiveSelected::Torus => drop(
737 gizmos
738 .primitive_3d(&TORUS, isometry, color)
739 .minor_resolution(resolution)
740 .major_resolution(resolution),
741 ),
742 PrimitiveSelected::Tetrahedron => {
743 gizmos.primitive_3d(&TETRAHEDRON, isometry, color);
744 }
745
746 PrimitiveSelected::Arc => {}
747 PrimitiveSelected::CircularSector => {}
748 PrimitiveSelected::CircularSegment => {}
749 }
750}More examples
154fn snap_to_player_system(
155 mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
156 player_transform: Single<&Transform, With<Player>>,
157) {
158 // Get the player translation in 2D
159 let player_translation = player_transform.translation.xy();
160
161 for mut enemy_transform in &mut query {
162 // Get the vector from the enemy ship to the player ship in 2D and normalize it.
163 let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
164
165 // Get the quaternion to rotate from the initial enemy facing direction to the direction
166 // facing the player
167 let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));
168
169 // Rotate the enemy to face the player
170 enemy_transform.rotation = rotate_to_player;
171 }
172}13fn draw_cursor(
14 camera_query: Single<(&Camera, &GlobalTransform)>,
15 ground: Single<&GlobalTransform, With<Ground>>,
16 window: Single<&Window>,
17 mut gizmos: Gizmos,
18) {
19 let (camera, camera_transform) = *camera_query;
20
21 if let Some(cursor_position) = window.cursor_position()
22 // Calculate a ray pointing from the camera into the world based on the cursor's position.
23 && let Ok(ray) = camera.viewport_to_world(camera_transform, cursor_position)
24 // Calculate if and where the ray is hitting the ground plane.
25 && let Some(point) = ray.plane_intersection_point(ground.translation(), InfinitePlane3d::new(ground.up()))
26 {
27 // Draw a circle just above the ground plane at that position.
28 gizmos.circle(
29 Isometry3d::new(
30 point + ground.up() * 0.01,
31 Quat::from_rotation_arc(Vec3::Z, ground.up().as_vec3()),
32 ),
33 0.2,
34 Color::WHITE,
35 );
36 }
37}99fn draw_example_collection(
100 mut gizmos: Gizmos,
101 mut my_gizmos: Gizmos<MyRoundGizmos>,
102 time: Res<Time>,
103) {
104 gizmos.grid(
105 Quat::from_rotation_x(PI / 2.),
106 UVec2::splat(20),
107 Vec2::new(2., 2.),
108 // Light gray
109 LinearRgba::gray(0.65),
110 );
111 gizmos.grid(
112 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
113 UVec2::splat(20),
114 Vec2::new(2., 2.),
115 PURPLE,
116 );
117 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
118
119 gizmos
120 .primitive_3d(
121 &Plane3d {
122 normal: Dir3::Y,
123 half_size: Vec2::splat(1.0),
124 },
125 Isometry3d::new(
126 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
127 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
128 ),
129 GREEN,
130 )
131 .cell_count(UVec2::new(5, 10))
132 .spacing(Vec2::new(0.2, 0.1));
133
134 gizmos.cube(
135 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
136 BLACK,
137 );
138 gizmos.rect(
139 Isometry3d::new(
140 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
141 Quat::from_rotation_y(PI / 2.),
142 ),
143 Vec2::splat(2.),
144 LIME,
145 );
146
147 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
148
149 let domain = Interval::EVERYWHERE;
150 let curve = FunctionCurve::new(domain, |t| {
151 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
152 });
153 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
154 let times_and_colors = (0..=resolution)
155 .map(|n| n as f32 / resolution as f32)
156 .map(|t| t * 5.0)
157 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
158 gizmos.curve_gradient_3d(curve, times_and_colors);
159
160 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
161
162 my_gizmos
163 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
164 .edge_radius(0.1)
165 .arc_resolution(4);
166
167 for y in [0., 0.5, 1.] {
168 gizmos.ray(
169 Vec3::new(1., y, 0.),
170 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
171 BLUE,
172 );
173 }
174
175 my_gizmos
176 .arc_3d(
177 180.0_f32.to_radians(),
178 0.2,
179 Isometry3d::new(
180 Vec3::ONE,
181 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
182 ),
183 ORANGE,
184 )
185 .resolution(10);
186
187 // Circles have 32 line-segments by default.
188 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
189
190 // You may want to increase this for larger circles or spheres.
191 my_gizmos
192 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
193 .resolution(64);
194 my_gizmos
195 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
196 .resolution(64);
197
198 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
199
200 // You can create more complex arrows using the arrow builder.
201 gizmos
202 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
203 .with_double_end()
204 .with_tip_length(0.5);
205}Sourcepub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Quat
pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Quat
Gets the minimal rotation for transforming from to either to or -to. This means
that the resulting quaternion will rotate from so that it is colinear with to.
The rotation is in the plane spanned by the two vectors. Will rotate at most 90 degrees.
The inputs must be unit vectors.
to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1.
§Panics
Will panic if from or to are not normalized when glam_assert is enabled.
Sourcepub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Quat
pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Quat
Gets the minimal rotation for transforming from to to. The resulting rotation is
around the z axis. Will rotate at most 180 degrees.
The inputs must be unit vectors.
from_rotation_arc_2d(from, to) * from ≈ to.
For near-singular cases (from≈to and from≈-to) the current implementation
is only accurate to about 0.001 (for f32).
§Panics
Will panic if from or to are not normalized when glam_assert is enabled.
Sourcepub fn look_to_lh(dir: Vec3, up: Vec3) -> Quat
pub fn look_to_lh(dir: Vec3, up: Vec3) -> Quat
Creates a quaterion rotation from a facing direction and an up direction.
For a left-handed view coordinate system with +X=right, +Y=up and +Z=forward.
§Panics
Will panic if up is not normalized when glam_assert is enabled.
Sourcepub fn look_to_rh(dir: Vec3, up: Vec3) -> Quat
pub fn look_to_rh(dir: Vec3, up: Vec3) -> Quat
Creates a quaterion rotation from facing direction and an up direction.
For a right-handed view coordinate system with +X=right, +Y=up and +Z=back.
§Panics
Will panic if dir and up are not normalized when glam_assert is enabled.
Sourcepub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Quat
pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Quat
Creates a left-handed view matrix using a camera position, a focal point, and an up direction.
For a left-handed view coordinate system with +X=right, +Y=up and +Z=forward.
§Panics
Will panic if up is not normalized when glam_assert is enabled.
Sourcepub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Quat
pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Quat
Creates a right-handed view matrix using a camera position, an up direction, and a focal point.
For a right-handed view coordinate system with +X=right, +Y=up and +Z=back.
§Panics
Will panic if up is not normalized when glam_assert is enabled.
Sourcepub fn to_axis_angle(self) -> (Vec3, f32)
pub fn to_axis_angle(self) -> (Vec3, f32)
Returns the rotation axis (normalized) and angle (in radians) of self.
Sourcepub fn to_scaled_axis(self) -> Vec3
pub fn to_scaled_axis(self) -> Vec3
Returns the rotation axis scaled by the rotation in radians.
Examples found in repository?
283fn bounding_shapes_2d(
284 shapes: Query<&Transform, With<Shape2d>>,
285 mut gizmos: Gizmos,
286 bounding_shape: Res<State<BoundingShape>>,
287) {
288 for transform in shapes.iter() {
289 // Get the rotation angle from the 3D rotation.
290 let rotation = transform.rotation.to_scaled_axis().z;
291 let rotation = Rot2::radians(rotation);
292 let isometry = Isometry2d::new(transform.translation.xy(), rotation);
293
294 match bounding_shape.get() {
295 BoundingShape::None => (),
296 BoundingShape::BoundingBox => {
297 // Get the AABB of the primitive with the rotation and translation of the mesh.
298 let aabb = HEART.aabb_2d(isometry);
299 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2., WHITE);
300 }
301 BoundingShape::BoundingSphere => {
302 // Get the bounding sphere of the primitive with the rotation and translation of the mesh.
303 let bounding_circle = HEART.bounding_circle(isometry);
304 gizmos
305 .circle_2d(bounding_circle.center(), bounding_circle.radius(), WHITE)
306 .resolution(64);
307 }
308 }
309 }
310}Sourcepub fn to_euler(self, order: EulerRot) -> (f32, f32, f32)
pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32)
Returns the rotation angles for the given euler rotation sequence.
Examples found in repository?
351fn move_free_camera(
352 new_transform: Transform,
353 mut free_camera_query: Query<
354 (&mut Transform, &mut FreeCameraState),
355 (With<Camera3d>, Without<MyCamera>),
356 >,
357) -> Result {
358 let (mut transform, mut state) = free_camera_query.single_mut()?;
359 *transform = new_transform;
360
361 // Update the yaw and pitch so that free camera orientation is updated correctly upon mouse grab
362 let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
363 state.yaw = yaw;
364 state.pitch = pitch;
365
366 Ok(())
367}More examples
104fn draw_bounds<Shape: Bounded2d + Send + Sync + 'static>(
105 q: Query<(&DrawBounds<Shape>, &GlobalTransform)>,
106 mut gizmos: Gizmos,
107) {
108 for (shape, transform) in &q {
109 let (_, rotation, translation) = transform.to_scale_rotation_translation();
110 let translation = translation.truncate();
111 let rotation = rotation.to_euler(EulerRot::XYZ).2;
112 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
113
114 let aabb = shape.0.aabb_2d(isometry);
115 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2.0, RED);
116
117 let bounding_circle = shape.0.bounding_circle(isometry);
118 gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE);
119 }
120}101fn render_shapes(mut gizmos: Gizmos, query: Query<(&Shape, &Transform)>) {
102 let color = GRAY;
103 for (shape, transform) in query.iter() {
104 let translation = transform.translation.xy();
105 let rotation = transform.rotation.to_euler(EulerRot::YXZ).2;
106 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
107 match shape {
108 Shape::Rectangle(r) => {
109 gizmos.primitive_2d(r, isometry, color);
110 }
111 Shape::Circle(c) => {
112 gizmos.primitive_2d(c, isometry, color);
113 }
114 Shape::Triangle(t) => {
115 gizmos.primitive_2d(t, isometry, color);
116 }
117 Shape::Line(l) => {
118 gizmos.primitive_2d(l, isometry, color);
119 }
120 Shape::Capsule(c) => {
121 gizmos.primitive_2d(c, isometry, color);
122 }
123 Shape::Polygon(p) => {
124 gizmos.primitive_2d(p, isometry, color);
125 }
126 }
127 }
128}
129
130#[derive(Component)]
131enum DesiredVolume {
132 Aabb,
133 Circle,
134}
135
136#[derive(Component, Debug)]
137enum CurrentVolume {
138 Aabb(Aabb2d),
139 Circle(BoundingCircle),
140}
141
142fn update_volumes(
143 mut commands: Commands,
144 query: Query<
145 (Entity, &DesiredVolume, &Shape, &Transform),
146 Or<(Changed<DesiredVolume>, Changed<Shape>, Changed<Transform>)>,
147 >,
148) {
149 for (entity, desired_volume, shape, transform) in query.iter() {
150 let translation = transform.translation.xy();
151 let rotation = transform.rotation.to_euler(EulerRot::YXZ).2;
152 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
153 match desired_volume {
154 DesiredVolume::Aabb => {
155 let aabb = match shape {
156 Shape::Rectangle(r) => r.aabb_2d(isometry),
157 Shape::Circle(c) => c.aabb_2d(isometry),
158 Shape::Triangle(t) => t.aabb_2d(isometry),
159 Shape::Line(l) => l.aabb_2d(isometry),
160 Shape::Capsule(c) => c.aabb_2d(isometry),
161 Shape::Polygon(p) => p.aabb_2d(isometry),
162 };
163 commands.entity(entity).insert(CurrentVolume::Aabb(aabb));
164 }
165 DesiredVolume::Circle => {
166 let circle = match shape {
167 Shape::Rectangle(r) => r.bounding_circle(isometry),
168 Shape::Circle(c) => c.bounding_circle(isometry),
169 Shape::Triangle(t) => t.bounding_circle(isometry),
170 Shape::Line(l) => l.bounding_circle(isometry),
171 Shape::Capsule(c) => c.bounding_circle(isometry),
172 Shape::Polygon(p) => p.bounding_circle(isometry),
173 };
174 commands
175 .entity(entity)
176 .insert(CurrentVolume::Circle(circle));
177 }
178 }
179 }
180}244fn rotate_camera(
245 accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
246 player: Single<(&mut Transform, &CameraSensitivity), With<Camera>>,
247) {
248 let (mut transform, camera_sensitivity) = player.into_inner();
249
250 let delta = accumulated_mouse_motion.delta;
251
252 if delta != Vec2::ZERO {
253 // Note that we are not multiplying by delta time here.
254 // The reason is that for mouse movement, we already get the full movement that happened since the last frame.
255 // This means that if we multiply by delta time, we will get a smaller rotation than intended by the user.
256 let delta_yaw = -delta.x * camera_sensitivity.x;
257 let delta_pitch = -delta.y * camera_sensitivity.y;
258
259 let (yaw, pitch, roll) = transform.rotation.to_euler(EulerRot::YXZ);
260 let yaw = yaw + delta_yaw;
261
262 // If the pitch was ±¹⁄₂ π, the camera would look straight up or down.
263 // When the user wants to move the camera back to the horizon, which way should the camera face?
264 // The camera has no way of knowing what direction was "forward" before landing in that extreme position,
265 // so the direction picked will for all intents and purposes be arbitrary.
266 // Another issue is that for mathematical reasons, the yaw will effectively be flipped when the pitch is at the extremes.
267 // To not run into these issues, we clamp the pitch to a safe range.
268 const PITCH_LIMIT: f32 = FRAC_PI_2 - 0.01;
269 let pitch = (pitch + delta_pitch).clamp(-PITCH_LIMIT, PITCH_LIMIT);
270
271 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
272 }
273}99fn orbit(
100 mut camera: Single<&mut Transform, With<Camera>>,
101 camera_settings: Res<CameraSettings>,
102 mouse_buttons: Res<ButtonInput<MouseButton>>,
103 mouse_motion: Res<AccumulatedMouseMotion>,
104 time: Res<Time>,
105) {
106 let delta = mouse_motion.delta;
107 let mut delta_roll = 0.0;
108
109 if mouse_buttons.pressed(MouseButton::Left) {
110 delta_roll -= 1.0;
111 }
112 if mouse_buttons.pressed(MouseButton::Right) {
113 delta_roll += 1.0;
114 }
115
116 // Mouse motion is one of the few inputs that should not be multiplied by delta time,
117 // as we are already receiving the full movement since the last frame was rendered. Multiplying
118 // by delta time here would make the movement slower that it should be.
119 let delta_pitch = delta.y * camera_settings.pitch_speed;
120 let delta_yaw = delta.x * camera_settings.yaw_speed;
121
122 // Conversely, we DO need to factor in delta time for mouse button inputs.
123 delta_roll *= camera_settings.roll_speed * time.delta_secs();
124
125 // Obtain the existing pitch, yaw, and roll values from the transform.
126 let (yaw, pitch, roll) = camera.rotation.to_euler(EulerRot::YXZ);
127
128 // Establish the new yaw and pitch, preventing the pitch value from exceeding our limits.
129 let pitch = (pitch + delta_pitch).clamp(
130 camera_settings.pitch_range.start,
131 camera_settings.pitch_range.end,
132 );
133 let roll = roll + delta_roll;
134 let yaw = yaw + delta_yaw;
135 camera.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
136
137 // Adjust the translation to maintain the correct orientation toward the orbit target.
138 // In our example it's a static target, but this could easily be customized.
139 let target = Vec3::ZERO;
140 camera.translation = target - camera.forward() * camera_settings.orbit_distance;
141}386fn process_move_input(
387 mut selections: Query<(&mut Transform, &Selection)>,
388 mouse_buttons: Res<ButtonInput<MouseButton>>,
389 mouse_motion: Res<AccumulatedMouseMotion>,
390 app_status: Res<AppStatus>,
391) {
392 // Only process drags when movement is selected.
393 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Move {
394 return;
395 }
396
397 for (mut transform, selection) in &mut selections {
398 if app_status.selection != *selection {
399 continue;
400 }
401
402 let position = transform.translation;
403
404 // Convert to spherical coordinates.
405 let radius = position.length();
406 let mut theta = acos(position.y / radius);
407 let mut phi = position.z.signum() * acos(position.x * position.xz().length_recip());
408
409 // Camera movement is the inverse of object movement.
410 let (phi_factor, theta_factor) = match *selection {
411 Selection::Camera => (1.0, -1.0),
412 Selection::DecalA | Selection::DecalB => (-1.0, 1.0),
413 };
414
415 // Adjust the spherical coordinates. Clamp the inclination to (0, π).
416 phi += phi_factor * mouse_motion.delta.x * MOVE_SPEED;
417 theta = f32::clamp(
418 theta + theta_factor * mouse_motion.delta.y * MOVE_SPEED,
419 0.001,
420 PI - 0.001,
421 );
422
423 // Convert spherical coordinates back to Cartesian coordinates.
424 transform.translation =
425 radius * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
426
427 // Look at the center, but preserve the previous roll angle.
428 let roll = transform.rotation.to_euler(EulerRot::YXZ).2;
429 transform.look_at(Vec3::ZERO, Vec3::Y);
430 let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
431 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
432 }
433}
434
435/// Processes a drag event that scales the selected target.
436fn process_scale_input(
437 mut selections: Query<(&mut Transform, &Selection)>,
438 mouse_buttons: Res<ButtonInput<MouseButton>>,
439 mouse_motion: Res<AccumulatedMouseMotion>,
440 app_status: Res<AppStatus>,
441) {
442 // Only process drags when the scaling operation is selected.
443 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Scale {
444 return;
445 }
446
447 for (mut transform, selection) in &mut selections {
448 if app_status.selection == *selection {
449 transform.scale *= 1.0 + mouse_motion.delta.x * SCALE_SPEED;
450 }
451 }
452}
453
454/// Processes a drag event that rotates the selected target along its local Z
455/// axis.
456fn process_roll_input(
457 mut selections: Query<(&mut Transform, &Selection)>,
458 mouse_buttons: Res<ButtonInput<MouseButton>>,
459 mouse_motion: Res<AccumulatedMouseMotion>,
460 app_status: Res<AppStatus>,
461) {
462 // Only process drags when the rolling operation is selected.
463 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Roll {
464 return;
465 }
466
467 for (mut transform, selection) in &mut selections {
468 if app_status.selection != *selection {
469 continue;
470 }
471
472 let (yaw, pitch, mut roll) = transform.rotation.to_euler(EulerRot::YXZ);
473 roll += mouse_motion.delta.x * ROLL_SPEED;
474 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
475 }
476}Sourcepub fn conjugate(self) -> Quat
pub fn conjugate(self) -> Quat
Returns the quaternion conjugate of self. For a unit quaternion the
conjugate is also the inverse.
Sourcepub fn inverse(self) -> Quat
pub fn inverse(self) -> Quat
Returns the inverse of a normalized quaternion.
Typically quaternion inverse returns the conjugate of a normalized quaternion.
Because self is assumed to already be unit length this method does not normalize
before returning the conjugate.
§Panics
Will panic if self is not normalized when glam_assert is enabled.
Sourcepub fn dot(self, rhs: Quat) -> f32
pub fn dot(self, rhs: Quat) -> f32
Computes the dot product of self and rhs. The dot product is
equal to the cosine of the angle between two quaternion rotations.
Sourcepub fn length_squared(self) -> f32
pub fn length_squared(self) -> f32
Computes the squared length of self.
This is generally faster than length() as it avoids a square
root operation.
Sourcepub fn length_recip(self) -> f32
pub fn length_recip(self) -> f32
Computes 1.0 / length().
For valid results, self must not be of length zero.
Sourcepub fn normalize(self) -> Quat
pub fn normalize(self) -> Quat
Returns self normalized to length 1.0.
For valid results, self must not be of length zero.
Panics
Will panic if self is zero length when glam_assert is enabled.
Sourcepub fn is_finite(self) -> bool
pub fn is_finite(self) -> bool
Returns true if, and only if, all elements are finite.
If any element is either NaN, positive or negative infinity, this will return false.
Sourcepub fn is_normalized(self) -> bool
pub fn is_normalized(self) -> bool
Returns whether self of length 1.0 or not.
Uses a precision threshold of 1e-6.
pub fn is_near_identity(self) -> bool
Sourcepub fn angle_between(self, rhs: Quat) -> f32
pub fn angle_between(self, rhs: Quat) -> f32
Returns the angle (in radians) for the minimal rotation for transforming this quaternion into another.
Both quaternions must be normalized.
§Panics
Will panic if self or rhs are not normalized when glam_assert is enabled.
Examples found in repository?
140fn rotate_ship(ship: Single<(&mut Ship, &mut Transform)>, time: Res<Time>) {
141 let (mut ship, mut ship_transform) = ship.into_inner();
142
143 if !ship.in_motion {
144 return;
145 }
146
147 let target_rotation = ship.target_transform.rotation;
148
149 ship_transform
150 .rotation
151 .smooth_nudge(&target_rotation, 3.0, time.delta_secs());
152
153 if ship_transform.rotation.angle_between(target_rotation) <= f32::EPSILON {
154 ship.in_motion = false;
155 }
156}Sourcepub fn rotate_towards(self, rhs: Quat, max_angle: f32) -> Quat
pub fn rotate_towards(self, rhs: Quat, max_angle: f32) -> Quat
Rotates towards rhs up to max_angle (in radians).
When max_angle is 0.0, the result will be equal to self. When max_angle is equal to
self.angle_between(rhs), the result will be equal to rhs. If max_angle is negative,
rotates towards the exact opposite of rhs. Will not go past the target.
Both quaternions must be normalized.
§Panics
Will panic if self or rhs are not normalized when glam_assert is enabled.
Sourcepub fn abs_diff_eq(self, rhs: Quat, max_abs_diff: f32) -> bool
pub fn abs_diff_eq(self, rhs: Quat, max_abs_diff: f32) -> bool
Returns true if the absolute difference of all elements between self and rhs
is less than or equal to max_abs_diff.
This can be used to compare if two quaternions contain similar elements. It works
best when comparing with a known value. The max_abs_diff that should be used used
depends on the values being compared against.
For more see comparing floating point numbers.
Sourcepub fn lerp(self, end: Quat, s: f32) -> Quat
pub fn lerp(self, end: Quat, s: f32) -> Quat
Performs a linear interpolation between self and rhs based on
the value s.
When s is 0.0, the result will be equal to self. When s
is 1.0, the result will be equal to rhs.
§Panics
Will panic if self or end are not normalized when glam_assert is enabled.
Examples found in repository?
More examples
101fn rotate_cube(
102 mut cubes: Query<(&mut Transform, &mut CubeState), Without<Center>>,
103 center_spheres: Query<&Transform, With<Center>>,
104 timer: Res<Time>,
105) {
106 // Calculate the point to circle around. (The position of the center_sphere)
107 let mut center: Vec3 = Vec3::ZERO;
108 for sphere in ¢er_spheres {
109 center += sphere.translation;
110 }
111 // Update the rotation of the cube(s).
112 for (mut transform, cube) in &mut cubes {
113 // Calculate the rotation of the cube if it would be looking at the sphere in the center.
114 let look_at_sphere = transform.looking_at(center, *transform.local_y());
115 // Interpolate between the current rotation and the fully turned rotation
116 // when looking at the sphere, with a given turn speed to get a smooth motion.
117 // With higher speed the curvature of the orbit would be smaller.
118 let incremental_turn_weight = cube.turn_speed * timer.delta_secs();
119 let old_rotation = transform.rotation;
120 transform.rotation = old_rotation.lerp(look_at_sphere.rotation, incremental_turn_weight);
121 }
122}Sourcepub fn slerp(self, end: Quat, s: f32) -> Quat
pub fn slerp(self, end: Quat, s: f32) -> Quat
Performs a spherical linear interpolation between self and end
based on the value s.
When s is 0.0, the result will be equal to self. When s
is 1.0, the result will be equal to end.
§Panics
Will panic if self or end are not normalized when glam_assert is enabled.
Examples found in repository?
More examples
187fn move_camera(
188 mut camera: Single<&mut Transform, With<FreeCameraController>>,
189 mut current_view: Local<usize>,
190 button: Res<ButtonInput<MouseButton>>,
191) {
192 if button.just_pressed(MouseButton::Left) {
193 *current_view = (*current_view + 1) % CAMERA_POSITIONS.len();
194 }
195 let target = CAMERA_POSITIONS[*current_view];
196 camera.translation = camera.translation.lerp(target.translation, 0.2);
197 camera.rotation = camera.rotation.slerp(target.rotation, 0.2);
198}Sourcepub fn mul_vec3(self, rhs: Vec3) -> Vec3
pub fn mul_vec3(self, rhs: Vec3) -> Vec3
Multiplies a quaternion and a 3D vector, returning the rotated vector.
§Panics
Will panic if self is not normalized when glam_assert is enabled.
Examples found in repository?
More examples
194fn rotate_camera(
195 mut camera: Query<&mut Transform, With<Camera>>,
196 app_status: Res<AppStatus>,
197 time: Res<Time>,
198 mut stopwatch: Local<Stopwatch>,
199) {
200 if app_status.light_mode == LightMode::EnvironmentMap {
201 stopwatch.tick(time.delta());
202 }
203
204 let now = stopwatch.elapsed_secs();
205 for mut transform in camera.iter_mut() {
206 *transform = Transform::from_translation(
207 Quat::from_rotation_y(now).mul_vec3(CAMERA_INITIAL_POSITION),
208 )
209 .looking_at(Vec3::ZERO, Vec3::Y);
210 }
211}Sourcepub fn mul_quat(self, rhs: Quat) -> Quat
pub fn mul_quat(self, rhs: Quat) -> Quat
Multiplies two quaternions. If they each represent a rotation, the result will represent the combined rotation.
Note that due to floating point rounding the result may not be perfectly normalized.
§Panics
Will panic if self or rhs are not normalized when glam_assert is enabled.
Sourcepub fn from_affine3(a: &Affine3) -> Quat
pub fn from_affine3(a: &Affine3) -> Quat
Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
Note if the input affine matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.
§Panics
Will panic if any input affine matrix column is not normalized when glam_assert is
enabled.
Sourcepub fn from_affine3a(a: &Affine3A) -> Quat
pub fn from_affine3a(a: &Affine3A) -> Quat
Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
Note if the input affine matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.
§Panics
Will panic if any input affine matrix column is not normalized when glam_assert is
enabled.
Sourcepub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A
pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A
Multiplies a quaternion and a 3D vector, returning the rotated vector.
pub fn as_dquat(self) -> DQuat
Trait Implementations§
Source§impl Add for Quat
impl Add for Quat
Source§impl AddAssign for Quat
impl AddAssign for Quat
Source§fn add_assign(&mut self, rhs: Quat)
fn add_assign(&mut self, rhs: Quat)
+= operation. Read moreSource§impl AddAssign<&Quat> for Quat
impl AddAssign<&Quat> for Quat
Source§fn add_assign(&mut self, rhs: &Quat)
fn add_assign(&mut self, rhs: &Quat)
+= operation. Read moreSource§impl Animatable for Quat
impl Animatable for Quat
impl Copy for Quat
Source§impl Curve<Quat> for CubicRotationCurve
impl Curve<Quat> for CubicRotationCurve
Source§fn sample_clamped(&self, t: f32) -> Quat
fn sample_clamped(&self, t: f32) -> Quat
t, clamping t to lie inside the
domain of the curve.Source§impl<'de> Deserialize<'de> for Quat
Deserialize expects a sequence of 4 values.
impl<'de> Deserialize<'de> for Quat
Deserialize expects a sequence of 4 values.
Source§fn deserialize<D>(
deserializer: D,
) -> Result<Quat, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<Quat, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl DivAssign<&f32> for Quat
impl DivAssign<&f32> for Quat
Source§fn div_assign(&mut self, rhs: &f32)
fn div_assign(&mut self, rhs: &f32)
/= operation. Read moreSource§impl DivAssign<f32> for Quat
impl DivAssign<f32> for Quat
Source§fn div_assign(&mut self, rhs: f32)
fn div_assign(&mut self, rhs: f32)
/= operation. Read moreSource§impl Ease for Quat
impl Ease for Quat
Source§impl From<Quat> for Isometry3d
impl From<Quat> for Isometry3d
Source§fn from(rotation: Quat) -> Isometry3d
fn from(rotation: Quat) -> Isometry3d
Source§impl FromReflect for Quat
impl FromReflect for Quat
Source§fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Quat>
fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Quat>
Self from a reflected value.Source§fn take_from_reflect(
reflect: Box<dyn PartialReflect>,
) -> Result<Self, Box<dyn PartialReflect>>
fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>
Self using,
constructing the value using from_reflect if that fails. Read moreSource§impl GetTypeRegistration for Quat
impl GetTypeRegistration for Quat
Source§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration for this type.Source§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
Source§impl IntoReturn for Quat
impl IntoReturn for Quat
Source§impl Mul for Quat
impl Mul for Quat
Source§fn mul(self, rhs: Quat) -> Quat
fn mul(self, rhs: Quat) -> Quat
Multiplies two quaternions. If they each represent a rotation, the result will represent the combined rotation.
Note that due to floating point rounding the result may not be perfectly normalized.
§Panics
Will panic if self or rhs are not normalized when glam_assert is enabled.
Source§impl MulAssign for Quat
impl MulAssign for Quat
Source§fn mul_assign(&mut self, rhs: Quat)
fn mul_assign(&mut self, rhs: Quat)
*= operation. Read moreSource§impl MulAssign<&Quat> for Quat
impl MulAssign<&Quat> for Quat
Source§fn mul_assign(&mut self, rhs: &Quat)
fn mul_assign(&mut self, rhs: &Quat)
*= operation. Read moreSource§impl MulAssign<&f32> for Quat
impl MulAssign<&f32> for Quat
Source§fn mul_assign(&mut self, rhs: &f32)
fn mul_assign(&mut self, rhs: &f32)
*= operation. Read moreSource§impl MulAssign<f32> for Quat
impl MulAssign<f32> for Quat
Source§fn mul_assign(&mut self, rhs: f32)
fn mul_assign(&mut self, rhs: f32)
*= operation. Read moreSource§impl PartialReflect for Quat
impl PartialReflect for Quat
Source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Source§fn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>
fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>
Source§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Source§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
Source§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
Source§fn reflect_owned(self: Box<Quat>) -> ReflectOwned
fn reflect_owned(self: Box<Quat>) -> ReflectOwned
Source§fn try_into_reflect(
self: Box<Quat>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<Quat>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
Source§fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
Source§fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
Source§fn into_partial_reflect(self: Box<Quat>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<Quat>) -> Box<dyn PartialReflect>
Source§fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
Source§fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
Source§fn reflect_partial_eq(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<bool>
fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>
Source§fn reflect_partial_cmp(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<Ordering>
fn reflect_partial_cmp( &self, value: &(dyn PartialReflect + 'static), ) -> Option<Ordering>
Source§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Source§fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
Self using reflection. Read moreSource§fn apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
Source§fn to_dynamic(&self) -> Box<dyn PartialReflect>
fn to_dynamic(&self) -> Box<dyn PartialReflect>
Source§fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
PartialReflect, combines reflect_clone and
take in a useful fashion, automatically constructing an appropriate
ReflectCloneError if the downcast fails.Source§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
Source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
impl Pod for Quat
Source§impl Reflect for Quat
impl Reflect for Quat
Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any. Read moreSource§fn into_reflect(self: Box<Quat>) -> Box<dyn Reflect>
fn into_reflect(self: Box<Quat>) -> Box<dyn Reflect>
Source§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
Source§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
Source§impl Serialize for Quat
Serialize as a sequence of 4 values.
impl Serialize for Quat
Serialize as a sequence of 4 values.
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
Source§impl StableInterpolate for Quat
impl StableInterpolate for Quat
Source§fn interpolate_stable(&self, other: &Quat, t: f32) -> Quat
fn interpolate_stable(&self, other: &Quat, t: f32) -> Quat
other given value using the parameter t. At
t = 0.0, a value equivalent to self is recovered, while t = 1.0 recovers a value
equivalent to other, with intermediate values interpolating between the two.
See the trait-level documentation for details.Source§fn interpolate_stable_assign(&mut self, other: &Self, t: f32)
fn interpolate_stable_assign(&mut self, other: &Self, t: f32)
interpolate_stable that assigns the result to self for convenience.Source§fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32)
fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32)
target at a given decay rate. The decay_rate
parameter controls how fast the distance between self and target decays relative to
the units of delta; the intended usage is for decay_rate to generally remain fixed,
while delta is something like delta_time from an updating system. This produces a
smooth following of the target that is independent of framerate. Read moreSource§impl Struct for Quat
impl Struct for Quat
Source§fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
name as a &dyn PartialReflect.Source§fn field_mut(
&mut self,
name: &str,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>
name as a
&mut dyn PartialReflect.Source§fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
index as a
&dyn PartialReflect.Source§fn field_at_mut(
&mut self,
index: usize,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>
index
as a &mut dyn PartialReflect.Source§fn index_of_name(&self, name: &str) -> Option<usize>
fn index_of_name(&self, name: &str) -> Option<usize>
Source§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
Source§fn to_dynamic_struct(&self) -> DynamicStruct
fn to_dynamic_struct(&self) -> DynamicStruct
DynamicStruct from this struct.Source§fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
None if TypeInfo is not available.Source§impl SubAssign for Quat
impl SubAssign for Quat
Source§fn sub_assign(&mut self, rhs: Quat)
fn sub_assign(&mut self, rhs: Quat)
-= operation. Read moreSource§impl SubAssign<&Quat> for Quat
impl SubAssign<&Quat> for Quat
Source§fn sub_assign(&mut self, rhs: &Quat)
fn sub_assign(&mut self, rhs: &Quat)
-= operation. Read moreSource§impl TypePath for Quat
impl TypePath for Quat
Source§fn type_path() -> &'static str
fn type_path() -> &'static str
Source§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
Source§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
Source§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
Auto Trait Implementations§
impl Freeze for Quat
impl RefUnwindSafe for Quat
impl Send for Quat
impl Sync for Quat
impl Unpin for Quat
impl UnsafeUnpin for Quat
impl UnwindSafe for Quat
Blanket Implementations§
impl<T> AnyBitPattern for Twhere
T: Pod,
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> Brush for T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
Source§type Bits = T
type Bits = T
Self must have the same layout as the specified Bits except for
the possible invalid bit patterns being checked during
is_valid_bit_pattern.Source§fn is_valid_bit_pattern(_bits: &T) -> bool
fn is_valid_bit_pattern(_bits: &T) -> bool
bits
as &Self.Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> ConditionalSend for Twhere
T: Send,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
Source§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path.Source§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
Source§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident.Source§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name.Source§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
Source§impl<T> DynamicTyped for Twhere
T: Typed,
impl<T> DynamicTyped for Twhere
T: Typed,
Source§fn reflect_type_info(&self) -> &'static TypeInfo
fn reflect_type_info(&self) -> &'static TypeInfo
Typed::type_info.impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromTemplate for T
impl<T> FromTemplate for T
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
Source§impl<S> GetField for Swhere
S: Struct,
impl<S> GetField for Swhere
S: Struct,
Source§impl<T> GetPath for T
impl<T> GetPath for T
Source§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
path. Read moreSource§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
path. Read moreSource§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path. Read moreSource§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path. Read moreSource§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T> HitDataExtra for T
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> Interleave for Twhere
T: Pod,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
impl<T> NoUninit for Twhere
T: Pod,
Source§impl<G> PatchFromTemplate for Gwhere
G: FromTemplate,
impl<G> PatchFromTemplate for Gwhere
G: FromTemplate,
Source§fn patch<F>(func: F) -> TemplatePatch<F, <G as PatchFromTemplate>::Template>
fn patch<F>(func: F) -> TemplatePatch<F, <G as PatchFromTemplate>::Template>
func, and turns it into a TemplatePatch.Source§impl<T> PatchTemplate for Twhere
T: Template,
impl<T> PatchTemplate for Twhere
T: Template,
Source§fn patch_template<F>(func: F) -> TemplatePatch<F, T>
fn patch_template<F>(func: F) -> TemplatePatch<F, T>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().impl<T> Reflectable for T
Source§impl<T> Serialize for T
impl<T> Serialize for T
fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>
fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>
impl<T> Settings for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.Source§impl<T> Template for T
impl<T> Template for T
Source§fn build_template(
&self,
_context: &mut TemplateContext<'_, '_>,
) -> Result<<T as Template>::Output, BevyError>
fn build_template( &self, _context: &mut TemplateContext<'_, '_>, ) -> Result<<T as Template>::Output, BevyError>
entity context to produce a Template::Output.Source§fn clone_template(&self) -> T
fn clone_template(&self) -> T
Clone.