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
162const CAMERA_POSITIONS: &[Transform] = &[
163 Transform {
164 translation: Vec3::new(1.5, 1.5, 1.5),
165 rotation: Quat::from_xyzw(-0.279, 0.364, 0.115, 0.880),
166 scale: Vec3::ONE,
167 },
168 Transform {
169 translation: Vec3::new(2.4, 0.0, 0.2),
170 rotation: Quat::from_xyzw(0.094, 0.676, 0.116, 0.721),
171 scale: Vec3::ONE,
172 },
173 Transform {
174 translation: Vec3::new(2.4, 2.6, -4.3),
175 rotation: Quat::from_xyzw(0.170, 0.908, 0.308, 0.225),
176 scale: Vec3::ONE,
177 },
178 Transform {
179 translation: Vec3::new(-1.0, 0.8, -1.2),
180 rotation: Quat::from_xyzw(-0.004, 0.909, 0.247, -0.335),
181 scale: Vec3::ONE,
182 },
183];
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?
179fn spawn_light(commands: &mut Commands, app_status: &AppStatus) {
180 // Because this light can become a directional light, point light, or spot
181 // light depending on the settings, we add the union of the components
182 // necessary for this light to behave as all three of those.
183 commands
184 .spawn((
185 create_directional_light(app_status),
186 Transform::from_rotation(Quat::from_array([
187 0.6539259,
188 -0.34646285,
189 0.36505926,
190 -0.5648683,
191 ]))
192 .with_translation(vec3(57.693, 34.334, -6.422)),
193 ))
194 // These two are needed for point lights.
195 .insert(CubemapVisibleEntities::default())
196 .insert(CubemapFrusta::default())
197 // These two are needed for spot lights.
198 .insert(VisibleMeshEntities::default())
199 .insert(Frustum::default());
200}
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
184fn button_system(
185 interaction_query: Query<
186 (&Interaction, &ComputedNodeTarget, &RotateCamera),
187 (Changed<Interaction>, With<Button>),
188 >,
189 mut camera_query: Query<&mut Transform, With<Camera>>,
190) {
191 for (interaction, computed_target, RotateCamera(direction)) in &interaction_query {
192 if let Interaction::Pressed = *interaction {
193 // Since TargetCamera propagates to the children, we can use it to find
194 // which side of the screen the button is on.
195 if let Some(mut camera_transform) = computed_target
196 .camera()
197 .and_then(|camera| camera_query.get_mut(camera).ok())
198 {
199 let angle = match direction {
200 Direction::Left => -0.1,
201 Direction::Right => 0.1,
202 };
203 camera_transform.rotate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, angle));
204 }
205 }
206 }
207}
298fn move_camera(
299 keyboard_input: Res<ButtonInput<KeyCode>>,
300 mut mouse_wheel_input: EventReader<MouseWheel>,
301 mut cameras: Query<&mut Transform, With<Camera>>,
302) {
303 let (mut distance_delta, mut theta_delta) = (0.0, 0.0);
304
305 // Handle keyboard events.
306 if keyboard_input.pressed(KeyCode::KeyW) {
307 distance_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
308 }
309 if keyboard_input.pressed(KeyCode::KeyS) {
310 distance_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
311 }
312 if keyboard_input.pressed(KeyCode::KeyA) {
313 theta_delta += CAMERA_KEYBOARD_ORBIT_SPEED;
314 }
315 if keyboard_input.pressed(KeyCode::KeyD) {
316 theta_delta -= CAMERA_KEYBOARD_ORBIT_SPEED;
317 }
318
319 // Handle mouse events.
320 for mouse_wheel_event in mouse_wheel_input.read() {
321 distance_delta -= mouse_wheel_event.y * CAMERA_MOUSE_WHEEL_ZOOM_SPEED;
322 }
323
324 // Update transforms.
325 for mut camera_transform in cameras.iter_mut() {
326 let local_z = camera_transform.local_z().as_vec3().normalize_or_zero();
327 if distance_delta != 0.0 {
328 camera_transform.translation = (camera_transform.translation.length() + distance_delta)
329 .clamp(CAMERA_ZOOM_RANGE.start, CAMERA_ZOOM_RANGE.end)
330 * local_z;
331 }
332 if theta_delta != 0.0 {
333 camera_transform
334 .translate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, theta_delta));
335 camera_transform.look_at(Vec3::ZERO, Vec3::Y);
336 }
337 }
338}
22fn setup(
23 mut commands: Commands,
24 mut meshes: ResMut<Assets<Mesh>>,
25 mut standard_materials: ResMut<Assets<StandardMaterial>>,
26 mut decal_standard_materials: ResMut<Assets<ForwardDecalMaterial<StandardMaterial>>>,
27 asset_server: Res<AssetServer>,
28) {
29 // Spawn the forward decal
30 commands.spawn((
31 Name::new("Decal"),
32 ForwardDecal,
33 MeshMaterial3d(decal_standard_materials.add(ForwardDecalMaterial {
34 base: StandardMaterial {
35 base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
36 ..default()
37 },
38 extension: ForwardDecalMaterialExt {
39 depth_fade_factor: 1.0,
40 },
41 })),
42 Transform::from_scale(Vec3::splat(4.0)),
43 ));
44
45 commands.spawn((
46 Name::new("Camera"),
47 Camera3d::default(),
48 CameraController::default(),
49 DepthPrepass, // Must enable the depth prepass to render forward decals
50 Transform::from_xyz(2.0, 9.5, 2.5).looking_at(Vec3::ZERO, Vec3::Y),
51 ));
52
53 let white_material = standard_materials.add(Color::WHITE);
54
55 commands.spawn((
56 Name::new("Floor"),
57 Mesh3d(meshes.add(Rectangle::from_length(10.0))),
58 MeshMaterial3d(white_material.clone()),
59 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
60 ));
61
62 // Spawn a few cube with random rotations to showcase how the decals behave with non-flat geometry
63 let num_obs = 10;
64 let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
65 for i in 0..num_obs {
66 for j in 0..num_obs {
67 let rotation_axis: [f32; 3] = rng.r#gen();
68 let rotation_vec: Vec3 = rotation_axis.into();
69 let rotation: u32 = rng.gen_range(0..360);
70 let transform = Transform::from_xyz(
71 (-num_obs + 1) as f32 / 2.0 + i as f32,
72 -0.2,
73 (-num_obs + 1) as f32 / 2.0 + j as f32,
74 )
75 .with_rotation(Quat::from_axis_angle(
76 rotation_vec.normalize_or_zero(),
77 (rotation as f32).to_radians(),
78 ));
79
80 commands.spawn((
81 Mesh3d(meshes.add(Cuboid::from_length(0.6))),
82 MeshMaterial3d(white_material.clone()),
83 transform,
84 ));
85 }
86 }
87
88 commands.spawn((
89 Name::new("Light"),
90 PointLight {
91 shadows_enabled: true,
92 ..default()
93 },
94 Transform::from_xyz(4.0, 8.0, 4.0),
95 ));
96}
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?
74fn setup(
75 mut commands: Commands,
76 mut meshes: ResMut<Assets<Mesh>>,
77 mut materials: ResMut<Assets<StandardMaterial>>,
78) {
79 // Make a box of planes facing inward so the laser gets trapped inside
80 let plane_mesh = meshes.add(Plane3d::default());
81 let plane_material = materials.add(Color::from(css::GRAY).with_alpha(0.01));
82 let create_plane = move |translation, rotation| {
83 (
84 Transform::from_translation(translation)
85 .with_rotation(Quat::from_scaled_axis(rotation)),
86 Mesh3d(plane_mesh.clone()),
87 MeshMaterial3d(plane_material.clone()),
88 )
89 };
90
91 commands.spawn(create_plane(vec3(0.0, 0.5, 0.0), Vec3::X * PI));
92 commands.spawn(create_plane(vec3(0.0, -0.5, 0.0), Vec3::ZERO));
93 commands.spawn(create_plane(vec3(0.5, 0.0, 0.0), Vec3::Z * FRAC_PI_2));
94 commands.spawn(create_plane(vec3(-0.5, 0.0, 0.0), Vec3::Z * -FRAC_PI_2));
95 commands.spawn(create_plane(vec3(0.0, 0.0, 0.5), Vec3::X * -FRAC_PI_2));
96 commands.spawn(create_plane(vec3(0.0, 0.0, -0.5), Vec3::X * FRAC_PI_2));
97
98 // Light
99 commands.spawn((
100 DirectionalLight::default(),
101 Transform::from_rotation(Quat::from_euler(EulerRot::XYZ, -0.1, 0.2, 0.0)),
102 ));
103
104 // Camera
105 commands.spawn((
106 Camera3d::default(),
107 Camera {
108 hdr: true,
109 ..default()
110 },
111 Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::ZERO, Vec3::Y),
112 Tonemapping::TonyMcMapface,
113 Bloom::default(),
114 ));
115}
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?
More examples
13fn setup(
14 mut commands: Commands,
15 mut meshes: ResMut<Assets<Mesh>>,
16 mut materials: ResMut<Assets<StandardMaterial>>,
17) {
18 // circular base
19 commands.spawn((
20 Mesh3d(meshes.add(Circle::new(4.0))),
21 MeshMaterial3d(materials.add(Color::WHITE)),
22 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
23 ));
24 // cube
25 commands.spawn((
26 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
27 MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
28 Transform::from_xyz(0.0, 0.5, 0.0),
29 ));
30 // light
31 commands.spawn((
32 PointLight {
33 shadows_enabled: true,
34 ..default()
35 },
36 Transform::from_xyz(4.0, 8.0, 4.0),
37 ));
38 // camera
39 commands.spawn((
40 Camera3d::default(),
41 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
42 ));
43}
33fn setup(
34 mut commands: Commands,
35 mut meshes: ResMut<Assets<Mesh>>,
36 mut materials: ResMut<Assets<StandardMaterial>>,
37) {
38 // circular base
39 commands.spawn((
40 Mesh3d(meshes.add(Circle::new(4.0))),
41 MeshMaterial3d(materials.add(Color::WHITE)),
42 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
43 ));
44 // cube
45 commands.spawn((
46 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
47 MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
48 Transform::from_xyz(0.0, 0.5, 0.0),
49 ));
50 // light
51 commands.spawn((
52 PointLight {
53 shadows_enabled: true,
54 ..default()
55 },
56 Transform::from_xyz(4.0, 8.0, 4.0),
57 ));
58 // camera
59 commands.spawn((
60 Camera3d::default(),
61 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
62 ));
63}
215fn setup_scene(
216 mut commands: Commands,
217 asset_server: Res<AssetServer>,
218 mut meshes: ResMut<Assets<Mesh>>,
219 mut materials: ResMut<Assets<StandardMaterial>>,
220) {
221 commands.spawn((
222 Camera3d::default(),
223 Transform::from_xyz(-10.0, 5.0, 13.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y),
224 ));
225
226 commands.spawn((
227 PointLight {
228 intensity: 10_000_000.0,
229 shadows_enabled: true,
230 ..default()
231 },
232 Transform::from_xyz(-4.0, 8.0, 13.0),
233 ));
234
235 commands.spawn((
236 SceneRoot(
237 asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")),
238 ),
239 Transform::from_scale(Vec3::splat(0.07)),
240 ));
241
242 // Ground
243
244 commands.spawn((
245 Mesh3d(meshes.add(Circle::new(7.0))),
246 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
247 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
248 ));
249}
25fn setup(
26 mut commands: Commands,
27 mut meshes: ResMut<Assets<Mesh>>,
28 mut materials: ResMut<Assets<StandardMaterial>>,
29) {
30 // circular base
31 commands.spawn((
32 Mesh3d(meshes.add(Circle::new(4.0))),
33 MeshMaterial3d(materials.add(Color::WHITE)),
34 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
35 ));
36
37 // cube
38 commands.spawn((
39 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
40 MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
41 Transform::from_xyz(0.0, 0.5, 0.0),
42 Cube(1.0),
43 ));
44
45 // test resource
46 commands.insert_resource(TestResource {
47 foo: Vec2::new(1.0, -1.0),
48 bar: false,
49 });
50
51 // light
52 commands.spawn((
53 PointLight {
54 shadows_enabled: true,
55 ..default()
56 },
57 Transform::from_xyz(4.0, 8.0, 4.0),
58 ));
59
60 // camera
61 commands.spawn((
62 Camera3d::default(),
63 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
64 ));
65}
119fn setup_scene(
120 mut commands: Commands,
121 asset_server: Res<AssetServer>,
122 mut meshes: ResMut<Assets<Mesh>>,
123 mut materials: ResMut<Assets<StandardMaterial>>,
124) {
125 // Spawn the camera.
126 commands.spawn((
127 Camera3d::default(),
128 Transform::from_xyz(-15.0, 10.0, 20.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y),
129 ));
130
131 // Spawn the light.
132 commands.spawn((
133 PointLight {
134 intensity: 10_000_000.0,
135 shadows_enabled: true,
136 ..default()
137 },
138 Transform::from_xyz(-4.0, 8.0, 13.0),
139 ));
140
141 // Spawn the fox.
142 commands.spawn((
143 SceneRoot(
144 asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")),
145 ),
146 Transform::from_scale(Vec3::splat(0.07)),
147 ));
148
149 // Spawn the ground.
150 commands.spawn((
151 Mesh3d(meshes.add(Circle::new(7.0))),
152 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
153 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
154 ));
155}
- examples/camera/custom_projection.rs
- examples/3d/skybox.rs
- examples/shader/custom_render_phase.rs
- examples/picking/simple_picking.rs
- examples/picking/debug_picking.rs
- examples/animation/custom_skinned_mesh.rs
- examples/math/custom_primitives.rs
- examples/app/headless_renderer.rs
- examples/3d/specular_tint.rs
- examples/testbed/3d.rs
- examples/stress_tests/many_cameras_lights.rs
- examples/3d/texture.rs
- examples/3d/decal.rs
- examples/ui/render_ui_to_texture.rs
- examples/3d/3d_shapes.rs
- examples/gizmos/3d_gizmos.rs
- examples/gizmos/light_gizmos.rs
- examples/3d/render_to_texture.rs
- examples/picking/mesh_picking.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/math/sampling_primitives.rs
- examples/3d/spotlight.rs
- examples/3d/anisotropy.rs
- examples/shader/shader_material_wesl.rs
- examples/transforms/scale.rs
- examples/transforms/align.rs
- examples/math/random_sampling.rs
- examples/3d/post_processing.rs
- examples/3d/color_grading.rs
- examples/3d/tonemapping.rs
- examples/transforms/transform.rs
- examples/animation/custom_skinned_mesh.rs
- examples/3d/auto_exposure.rs
- examples/3d/atmosphere.rs
- examples/3d/blend_modes.rs
- examples/animation/eased_motion.rs
- examples/games/alien_cake_addict.rs
- examples/3d/meshlet.rs
- examples/gizmos/3d_gizmos.rs
- examples/stress_tests/many_foxes.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
37fn setup(asset_server: Res<AssetServer>, mut commands: Commands) {
38 commands.insert_resource(MorphData {
39 the_wave: asset_server
40 .load(GltfAssetLabel::Animation(2).from_asset("models/animated/MorphStressTest.gltf")),
41 mesh: asset_server.load(
42 GltfAssetLabel::Primitive {
43 mesh: 0,
44 primitive: 0,
45 }
46 .from_asset("models/animated/MorphStressTest.gltf"),
47 ),
48 });
49 commands.spawn(SceneRoot(asset_server.load(
50 GltfAssetLabel::Scene(0).from_asset("models/animated/MorphStressTest.gltf"),
51 )));
52 commands.spawn((
53 DirectionalLight::default(),
54 Transform::from_rotation(Quat::from_rotation_z(PI / 2.0)),
55 ));
56 commands.spawn((
57 Camera3d::default(),
58 Transform::from_xyz(3.0, 2.1, 10.2).looking_at(Vec3::ZERO, Vec3::Y),
59 ));
60}
- examples/animation/gltf_skinned_mesh.rs
- examples/stress_tests/many_sprites.rs
- examples/testbed/2d.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/animation/custom_skinned_mesh.rs
- examples/stress_tests/many_text2d.rs
- examples/camera/2d_screen_shake.rs
- examples/3d/motion_blur.rs
- examples/picking/sprite_picking.rs
- examples/2d/mesh2d_arcs.rs
- examples/3d/pbr.rs
- examples/testbed/full_ui.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
373fn spin_large_cube(mut large_cubes: Query<&mut Transform, With<LargeCube>>) {
374 for mut transform in &mut large_cubes {
375 transform.rotate(Quat::from_euler(
376 EulerRot::XYZ,
377 0.13 * ROTATION_SPEED,
378 0.29 * ROTATION_SPEED,
379 0.35 * ROTATION_SPEED,
380 ));
381 }
382}
383
384/// Spawns a directional light to illuminate the scene.
385fn spawn_light(commands: &mut Commands) {
386 commands
387 .spawn(DirectionalLight::default())
388 .insert(Transform::from_rotation(Quat::from_euler(
389 EulerRot::ZYX,
390 0.0,
391 PI * -0.15,
392 PI * -0.15,
393 )));
394}
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}
55fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
56 commands.spawn((
57 Camera3d::default(),
58 Transform::from_xyz(4.0, 4.0, 12.0).looking_at(Vec3::new(0.0, 0.0, 0.5), Vec3::Y),
59 ));
60
61 commands.spawn((
62 Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
63 DirectionalLight::default(),
64 ));
65
66 commands.spawn(SceneRoot(asset_server.load(
67 GltfAssetLabel::Scene(0).from_asset("models/GltfPrimitives/gltf_primitives.glb"),
68 )));
69}
140fn light_sway(time: Res<Time>, mut query: Query<(&mut Transform, &mut SpotLight)>) {
141 for (mut transform, mut angles) in query.iter_mut() {
142 transform.rotation = Quat::from_euler(
143 EulerRot::XYZ,
144 -FRAC_PI_2 + ops::sin(time.elapsed_secs() * 0.67 * 3.0) * 0.5,
145 ops::sin(time.elapsed_secs() * 3.0) * 0.5,
146 0.0,
147 );
148 let angle = (ops::sin(time.elapsed_secs() * 1.2) + 1.0) * (FRAC_PI_4 - 0.1);
149 angles.inner_angle = angle * 0.8;
150 angles.outer_angle = angle;
151 }
152}
- examples/asset/multi_asset_sync.rs
- examples/animation/animated_mesh.rs
- examples/3d/volumetric_fog.rs
- examples/3d/post_processing.rs
- examples/3d/pcss.rs
- examples/3d/color_grading.rs
- examples/3d/tonemapping.rs
- examples/stress_tests/many_materials.rs
- examples/testbed/3d.rs
- examples/3d/mesh_ray_cast.rs
- examples/camera/camera_orbit.rs
- examples/animation/animated_mesh_events.rs
- examples/3d/clustered_decals.rs
- examples/3d/ssao.rs
- examples/camera/first_person_view_model.rs
- examples/3d/visibility_range.rs
- examples/animation/animated_mesh_control.rs
- examples/3d/shadow_caster_receiver.rs
- examples/3d/anti_aliasing.rs
- examples/3d/meshlet.rs
- examples/stress_tests/many_foxes.rs
- examples/3d/split_screen.rs
- examples/3d/../helpers/camera_controller.rs
- examples/3d/deferred_rendering.rs
- examples/3d/transmission.rs
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?
595fn rotate_primitive_2d_meshes(
596 mut primitives_2d: Query<
597 (&mut Transform, &ViewVisibility),
598 (With<PrimitiveData>, With<MeshDim2>),
599 >,
600 time: Res<Time>,
601) {
602 let rotation_2d = Quat::from_mat3(&Mat3::from_angle(time.elapsed_secs()));
603 primitives_2d
604 .iter_mut()
605 .filter(|(_, vis)| vis.get())
606 .for_each(|(mut transform, _)| {
607 transform.rotation = rotation_2d;
608 });
609}
More examples
137fn track_targets(
138 // `Single` ensures the system runs ONLY when exactly one matching entity exists.
139 mut player: Single<(&mut Transform, &Player)>,
140 // `Option<Single>` ensures that the system runs ONLY when zero or one matching entity exists.
141 enemy: Option<Single<&Transform, (With<Enemy>, Without<Player>)>>,
142 time: Res<Time>,
143) {
144 let (player_transform, player) = &mut *player;
145 if let Some(enemy_transform) = enemy {
146 // Enemy found, rotate and move towards it.
147 let delta = enemy_transform.translation - player_transform.translation;
148 let distance = delta.length();
149 let front = delta / distance;
150 let up = Vec3::Z;
151 let side = front.cross(up);
152 player_transform.rotation = Quat::from_mat3(&Mat3::from_cols(side, front, up));
153 let max_step = distance - player.min_follow_radius;
154 if 0.0 < max_step {
155 let velocity = (player.speed * time.delta_secs()).min(max_step);
156 player_transform.translation += front * velocity;
157 }
158 } else {
159 // 0 or multiple enemies found, keep searching.
160 player_transform.rotate_axis(Dir3::Z, player.rotation_speed * time.delta_secs());
161 }
162}
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?
611fn rotate_primitive_3d_meshes(
612 mut primitives_3d: Query<
613 (&mut Transform, &ViewVisibility),
614 (With<PrimitiveData>, With<MeshDim3>),
615 >,
616 time: Res<Time>,
617) {
618 let rotation_3d = Quat::from_rotation_arc(
619 Vec3::Z,
620 Vec3::new(
621 ops::sin(time.elapsed_secs()),
622 ops::cos(time.elapsed_secs()),
623 ops::sin(time.elapsed_secs()) * 0.5,
624 )
625 .try_normalize()
626 .unwrap_or(Vec3::Z),
627 );
628 primitives_3d
629 .iter_mut()
630 .filter(|(_, vis)| vis.get())
631 .for_each(|(mut transform, _)| {
632 transform.rotation = rotation_3d;
633 });
634}
635
636fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
637 const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
638 let rotation = Quat::from_rotation_arc(
639 Vec3::Z,
640 Vec3::new(
641 ops::sin(time.elapsed_secs()),
642 ops::cos(time.elapsed_secs()),
643 ops::sin(time.elapsed_secs()) * 0.5,
644 )
645 .try_normalize()
646 .unwrap_or(Vec3::Z),
647 );
648 let isometry = Isometry3d::new(POSITION, rotation);
649 let color = Color::WHITE;
650 let resolution = 10;
651
652 #[expect(
653 clippy::match_same_arms,
654 reason = "Certain primitives don't have any 3D rendering support yet."
655 )]
656 match state.get() {
657 PrimitiveSelected::RectangleAndCuboid => {
658 gizmos.primitive_3d(&CUBOID, isometry, color);
659 }
660 PrimitiveSelected::CircleAndSphere => drop(
661 gizmos
662 .primitive_3d(&SPHERE, isometry, color)
663 .resolution(resolution),
664 ),
665 PrimitiveSelected::Ellipse => {}
666 PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, isometry, color),
667 PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, isometry, color)),
668 PrimitiveSelected::Line => gizmos.primitive_3d(&LINE3D, isometry, color),
669 PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, isometry, color),
670 PrimitiveSelected::Polyline => gizmos.primitive_3d(&POLYLINE_3D, isometry, color),
671 PrimitiveSelected::Polygon => {}
672 PrimitiveSelected::RegularPolygon => {}
673 PrimitiveSelected::Capsule => drop(
674 gizmos
675 .primitive_3d(&CAPSULE_3D, isometry, color)
676 .resolution(resolution),
677 ),
678 PrimitiveSelected::Cylinder => drop(
679 gizmos
680 .primitive_3d(&CYLINDER, isometry, color)
681 .resolution(resolution),
682 ),
683 PrimitiveSelected::Cone => drop(
684 gizmos
685 .primitive_3d(&CONE, isometry, color)
686 .resolution(resolution),
687 ),
688 PrimitiveSelected::ConicalFrustum => {
689 gizmos.primitive_3d(&CONICAL_FRUSTUM, isometry, color);
690 }
691
692 PrimitiveSelected::Torus => drop(
693 gizmos
694 .primitive_3d(&TORUS, isometry, color)
695 .minor_resolution(resolution)
696 .major_resolution(resolution),
697 ),
698 PrimitiveSelected::Tetrahedron => {
699 gizmos.primitive_3d(&TETRAHEDRON, isometry, color);
700 }
701
702 PrimitiveSelected::Arc => {}
703 PrimitiveSelected::CircularSector => {}
704 PrimitiveSelected::CircularSegment => {}
705 }
706}
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 windows: Query<&Window>,
17 mut gizmos: Gizmos,
18) {
19 let Ok(windows) = windows.single() else {
20 return;
21 };
22
23 let (camera, camera_transform) = *camera_query;
24
25 let Some(cursor_position) = windows.cursor_position() else {
26 return;
27 };
28
29 // Calculate a ray pointing from the camera into the world based on the cursor's position.
30 let Ok(ray) = camera.viewport_to_world(camera_transform, cursor_position) else {
31 return;
32 };
33
34 // Calculate if and where the ray is hitting the ground plane.
35 let Some(distance) =
36 ray.intersect_plane(ground.translation(), InfinitePlane3d::new(ground.up()))
37 else {
38 return;
39 };
40 let point = ray.get_point(distance);
41
42 // Draw a circle just above the ground plane at that position.
43 gizmos.circle(
44 Isometry3d::new(
45 point + ground.up() * 0.01,
46 Quat::from_rotation_arc(Vec3::Z, ground.up().as_vec3()),
47 ),
48 0.2,
49 Color::WHITE,
50 );
51}
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
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 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?
182fn bounding_shapes_2d(
183 shapes: Query<&Transform, With<Shape2d>>,
184 mut gizmos: Gizmos,
185 bounding_shape: Res<State<BoundingShape>>,
186) {
187 for transform in shapes.iter() {
188 // Get the rotation angle from the 3D rotation.
189 let rotation = transform.rotation.to_scaled_axis().z;
190 let rotation = Rot2::radians(rotation);
191 let isometry = Isometry2d::new(transform.translation.xy(), rotation);
192
193 match bounding_shape.get() {
194 BoundingShape::None => (),
195 BoundingShape::BoundingBox => {
196 // Get the AABB of the primitive with the rotation and translation of the mesh.
197 let aabb = HEART.aabb_2d(isometry);
198 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2., WHITE);
199 }
200 BoundingShape::BoundingSphere => {
201 // Get the bounding sphere of the primitive with the rotation and translation of the mesh.
202 let bounding_circle = HEART.bounding_circle(isometry);
203 gizmos
204 .circle_2d(bounding_circle.center(), bounding_circle.radius(), WHITE)
205 .resolution(64);
206 }
207 }
208 }
209}
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?
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}
More examples
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}
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}
394fn process_move_input(
395 mut selections: Query<(&mut Transform, &Selection)>,
396 mouse_buttons: Res<ButtonInput<MouseButton>>,
397 mouse_motion: Res<AccumulatedMouseMotion>,
398 app_status: Res<AppStatus>,
399) {
400 // Only process drags when movement is selected.
401 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Move {
402 return;
403 }
404
405 for (mut transform, selection) in &mut selections {
406 if app_status.selection != *selection {
407 continue;
408 }
409
410 let position = transform.translation;
411
412 // Convert to spherical coordinates.
413 let radius = position.length();
414 let mut theta = acos(position.y / radius);
415 let mut phi = position.z.signum() * acos(position.x * position.xz().length_recip());
416
417 // Camera movement is the inverse of object movement.
418 let (phi_factor, theta_factor) = match *selection {
419 Selection::Camera => (1.0, -1.0),
420 Selection::DecalA | Selection::DecalB => (-1.0, 1.0),
421 };
422
423 // Adjust the spherical coordinates. Clamp the inclination to (0, π).
424 phi += phi_factor * mouse_motion.delta.x * MOVE_SPEED;
425 theta = f32::clamp(
426 theta + theta_factor * mouse_motion.delta.y * MOVE_SPEED,
427 0.001,
428 PI - 0.001,
429 );
430
431 // Convert spherical coordinates back to Cartesian coordinates.
432 transform.translation =
433 radius * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
434
435 // Look at the center, but preserve the previous roll angle.
436 let roll = transform.rotation.to_euler(EulerRot::YXZ).2;
437 transform.look_at(Vec3::ZERO, Vec3::Y);
438 let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
439 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
440 }
441}
442
443/// Processes a drag event that scales the selected target.
444fn process_scale_input(
445 mut selections: Query<(&mut Transform, &Selection)>,
446 mouse_buttons: Res<ButtonInput<MouseButton>>,
447 mouse_motion: Res<AccumulatedMouseMotion>,
448 app_status: Res<AppStatus>,
449) {
450 // Only process drags when the scaling operation is selected.
451 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Scale {
452 return;
453 }
454
455 for (mut transform, selection) in &mut selections {
456 if app_status.selection == *selection {
457 transform.scale *= 1.0 + mouse_motion.delta.x * SCALE_SPEED;
458 }
459 }
460}
461
462/// Processes a drag event that rotates the selected target along its local Z
463/// axis.
464fn process_roll_input(
465 mut selections: Query<(&mut Transform, &Selection)>,
466 mouse_buttons: Res<ButtonInput<MouseButton>>,
467 mouse_motion: Res<AccumulatedMouseMotion>,
468 app_status: Res<AppStatus>,
469) {
470 // Only process drags when the rolling operation is selected.
471 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Roll {
472 return;
473 }
474
475 for (mut transform, selection) in &mut selections {
476 if app_status.selection != *selection {
477 continue;
478 }
479
480 let (yaw, pitch, mut roll) = transform.rotation.to_euler(EulerRot::YXZ);
481 roll += mouse_motion.delta.x * ROLL_SPEED;
482 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
483 }
484}
208fn move_player(
209 accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
210 player: Single<(&mut Transform, &CameraSensitivity), With<Player>>,
211) {
212 let (mut transform, camera_sensitivity) = player.into_inner();
213
214 let delta = accumulated_mouse_motion.delta;
215
216 if delta != Vec2::ZERO {
217 // Note that we are not multiplying by delta_time here.
218 // The reason is that for mouse movement, we already get the full movement that happened since the last frame.
219 // This means that if we multiply by delta_time, we will get a smaller rotation than intended by the user.
220 // This situation is reversed when reading e.g. analog input from a gamepad however, where the same rules
221 // as for keyboard input apply. Such an input should be multiplied by delta_time to get the intended rotation
222 // independent of the framerate.
223 let delta_yaw = -delta.x * camera_sensitivity.x;
224 let delta_pitch = -delta.y * camera_sensitivity.y;
225
226 let (yaw, pitch, roll) = transform.rotation.to_euler(EulerRot::YXZ);
227 let yaw = yaw + delta_yaw;
228
229 // If the pitch was ±¹⁄₂ π, the camera would look straight up or down.
230 // When the user wants to move the camera back to the horizon, which way should the camera face?
231 // The camera has no way of knowing what direction was "forward" before landing in that extreme position,
232 // so the direction picked will for all intents and purposes be arbitrary.
233 // Another issue is that for mathematical reasons, the yaw will effectively be flipped when the pitch is at the extremes.
234 // To not run into these issues, we clamp the pitch to a safe range.
235 const PITCH_LIMIT: f32 = FRAC_PI_2 - 0.01;
236 let pitch = (pitch + delta_pitch).clamp(-PITCH_LIMIT, PITCH_LIMIT);
237
238 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
239 }
240}
127fn run_camera_controller(
128 time: Res<Time>,
129 mut windows: Query<&mut Window>,
130 accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
131 accumulated_mouse_scroll: Res<AccumulatedMouseScroll>,
132 mouse_button_input: Res<ButtonInput<MouseButton>>,
133 key_input: Res<ButtonInput<KeyCode>>,
134 mut toggle_cursor_grab: Local<bool>,
135 mut mouse_cursor_grab: Local<bool>,
136 mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>,
137) {
138 let dt = time.delta_secs();
139
140 let Ok((mut transform, mut controller)) = query.single_mut() else {
141 return;
142 };
143
144 if !controller.initialized {
145 let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
146 controller.yaw = yaw;
147 controller.pitch = pitch;
148 controller.initialized = true;
149 info!("{}", *controller);
150 }
151 if !controller.enabled {
152 return;
153 }
154
155 let mut scroll = 0.0;
156
157 let amount = match accumulated_mouse_scroll.unit {
158 MouseScrollUnit::Line => accumulated_mouse_scroll.delta.y,
159 MouseScrollUnit::Pixel => accumulated_mouse_scroll.delta.y / 16.0,
160 };
161 scroll += amount;
162 controller.walk_speed += scroll * controller.scroll_factor * controller.walk_speed;
163 controller.run_speed = controller.walk_speed * 3.0;
164
165 // Handle key input
166 let mut axis_input = Vec3::ZERO;
167 if key_input.pressed(controller.key_forward) {
168 axis_input.z += 1.0;
169 }
170 if key_input.pressed(controller.key_back) {
171 axis_input.z -= 1.0;
172 }
173 if key_input.pressed(controller.key_right) {
174 axis_input.x += 1.0;
175 }
176 if key_input.pressed(controller.key_left) {
177 axis_input.x -= 1.0;
178 }
179 if key_input.pressed(controller.key_up) {
180 axis_input.y += 1.0;
181 }
182 if key_input.pressed(controller.key_down) {
183 axis_input.y -= 1.0;
184 }
185
186 let mut cursor_grab_change = false;
187 if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
188 *toggle_cursor_grab = !*toggle_cursor_grab;
189 cursor_grab_change = true;
190 }
191 if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
192 *mouse_cursor_grab = true;
193 cursor_grab_change = true;
194 }
195 if mouse_button_input.just_released(controller.mouse_key_cursor_grab) {
196 *mouse_cursor_grab = false;
197 cursor_grab_change = true;
198 }
199 let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab;
200
201 // Apply movement update
202 if axis_input != Vec3::ZERO {
203 let max_speed = if key_input.pressed(controller.key_run) {
204 controller.run_speed
205 } else {
206 controller.walk_speed
207 };
208 controller.velocity = axis_input.normalize() * max_speed;
209 } else {
210 let friction = controller.friction.clamp(0.0, 1.0);
211 controller.velocity *= 1.0 - friction;
212 if controller.velocity.length_squared() < 1e-6 {
213 controller.velocity = Vec3::ZERO;
214 }
215 }
216 let forward = *transform.forward();
217 let right = *transform.right();
218 transform.translation += controller.velocity.x * dt * right
219 + controller.velocity.y * dt * Vec3::Y
220 + controller.velocity.z * dt * forward;
221
222 // Handle cursor grab
223 if cursor_grab_change {
224 if cursor_grab {
225 for mut window in &mut windows {
226 if !window.focused {
227 continue;
228 }
229
230 window.cursor_options.grab_mode = CursorGrabMode::Locked;
231 window.cursor_options.visible = false;
232 }
233 } else {
234 for mut window in &mut windows {
235 window.cursor_options.grab_mode = CursorGrabMode::None;
236 window.cursor_options.visible = true;
237 }
238 }
239 }
240
241 // Handle mouse input
242 if accumulated_mouse_motion.delta != Vec2::ZERO && cursor_grab {
243 // Apply look update
244 controller.pitch = (controller.pitch
245 - accumulated_mouse_motion.delta.y * RADIANS_PER_DOT * controller.sensitivity)
246 .clamp(-PI / 2., PI / 2.);
247 controller.yaw -=
248 accumulated_mouse_motion.delta.x * RADIANS_PER_DOT * controller.sensitivity;
249 transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
250 }
251}
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 a 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
185fn move_camera(
186 mut camera: Single<&mut Transform, With<CameraController>>,
187 mut current_view: Local<usize>,
188 button: Res<ButtonInput<MouseButton>>,
189) {
190 if button.just_pressed(MouseButton::Left) {
191 *current_view = (*current_view + 1) % CAMERA_POSITIONS.len();
192 }
193 let target = CAMERA_POSITIONS[*current_view];
194 camera.translation = camera.translation.lerp(target.translation, 0.2);
195 camera.rotation = camera.rotation.slerp(target.rotation, 0.2);
196}
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?
192fn rotate_camera(
193 mut camera: Query<&mut Transform, With<Camera>>,
194 app_status: Res<AppStatus>,
195 time: Res<Time>,
196 mut stopwatch: Local<Stopwatch>,
197) {
198 if app_status.light_mode == LightMode::EnvironmentMap {
199 stopwatch.tick(time.delta());
200 }
201
202 let now = stopwatch.elapsed_secs();
203 for mut transform in camera.iter_mut() {
204 *transform = Transform::from_translation(
205 Quat::from_rotation_y(now).mul_vec3(CAMERA_INITIAL_POSITION),
206 )
207 .looking_at(Vec3::ZERO, Vec3::Y);
208 }
209}
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.
Examples found in repository?
136fn screen_shake(
137 time: Res<Time>,
138 mut screen_shake: ResMut<ScreenShake>,
139 mut query: Query<(&mut Camera, &mut Transform)>,
140) {
141 let mut rng = ChaCha8Rng::from_entropy();
142 let shake = screen_shake.trauma * screen_shake.trauma;
143 let angle = (screen_shake.max_angle * shake).to_radians() * rng.gen_range(-1.0..1.0);
144 let offset_x = screen_shake.max_offset * shake * rng.gen_range(-1.0..1.0);
145 let offset_y = screen_shake.max_offset * shake * rng.gen_range(-1.0..1.0);
146
147 if shake > 0.0 {
148 for (mut camera, mut transform) in query.iter_mut() {
149 // Position
150 let sub_view = camera.sub_camera_view.as_mut().unwrap();
151 let target = sub_view.offset
152 + Vec2 {
153 x: offset_x,
154 y: offset_y,
155 };
156 sub_view
157 .offset
158 .smooth_nudge(&target, CAMERA_DECAY_RATE, time.delta_secs());
159
160 // Rotation
161 let rotation = Quat::from_rotation_z(angle);
162 transform.rotation = transform
163 .rotation
164 .interpolate_stable(&(transform.rotation.mul_quat(rotation)), CAMERA_DECAY_RATE);
165 }
166 } else {
167 // return camera to the latest position of player (it's fixed in this example case)
168 if let Ok((mut camera, mut transform)) = query.single_mut() {
169 let sub_view = camera.sub_camera_view.as_mut().unwrap();
170 let target = screen_shake.latest_position.unwrap();
171 sub_view
172 .offset
173 .smooth_nudge(&target, 1.0, time.delta_secs());
174 transform.rotation = transform.rotation.interpolate_stable(&Quat::IDENTITY, 0.1);
175 }
176 }
177 // Decay the trauma over time
178 screen_shake.trauma -= TRAUMA_DECAY_SPEED * time.delta_secs();
179 screen_shake.trauma = screen_shake.trauma.clamp(0.0, 1.0);
180}
Sourcepub fn from_affine3(a: &Affine3A) -> Quat
pub fn from_affine3(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 Animatable for Quat
impl Animatable 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 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 GetOwnership for &Quat
impl GetOwnership for &Quat
Source§impl GetOwnership for &mut Quat
impl GetOwnership for &mut Quat
Source§impl GetOwnership for Quat
impl GetOwnership for Quat
Source§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 IntoReturn for &mut Quat
impl IntoReturn for &mut Quat
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)
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 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 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 clone_value(&self) -> Box<dyn PartialReflect>
fn clone_value(&self) -> Box<dyn PartialReflect>
reflect_clone
. To convert reflected values to dynamic ones, use to_dynamic
.Self
into its dynamic representation. Read moreSource§fn to_dynamic(&self) -> Box<dyn PartialReflect>
fn to_dynamic(&self) -> Box<dyn PartialReflect>
Source§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
Source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
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 name_at(&self, index: usize) -> Option<&str>
fn name_at(&self, index: usize) -> Option<&str>
index
.Source§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn to_dynamic_struct(&self) -> DynamicStruct
Source§fn clone_dynamic(&self) -> DynamicStruct
fn clone_dynamic(&self) -> DynamicStruct
to_dynamic_struct
insteadDynamicStruct
.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 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>
impl Copy for Quat
impl Pod for Quat
Auto Trait Implementations§
impl Freeze for Quat
impl RefUnwindSafe for Quat
impl Send for Quat
impl Sync for Quat
impl Unpin for Quat
impl UnwindSafe for Quat
Blanket Implementations§
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
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,
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
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
.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> 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> 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> ⓘ
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<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> 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.Source§impl<T> Pointable for T
impl<T> Pointable for T
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()
.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>
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.