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?
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
const CAMERA_POSITIONS: &[Transform] = &[
Transform {
translation: Vec3::new(1.5, 1.5, 1.5),
rotation: Quat::from_xyzw(-0.279, 0.364, 0.115, 0.880),
scale: Vec3::ONE,
},
Transform {
translation: Vec3::new(2.4, 0.0, 0.2),
rotation: Quat::from_xyzw(0.094, 0.676, 0.116, 0.721),
scale: Vec3::ONE,
},
Transform {
translation: Vec3::new(2.4, 2.6, -4.3),
rotation: Quat::from_xyzw(0.170, 0.908, 0.308, 0.225),
scale: Vec3::ONE,
},
Transform {
translation: Vec3::new(-1.0, 0.8, -1.2),
rotation: Quat::from_xyzw(-0.004, 0.909, 0.247, -0.335),
scale: Vec3::ONE,
},
];
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.
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
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
fn button_system(
interaction_query: Query<
(&Interaction, &TargetCamera, &RotateCamera),
(Changed<Interaction>, With<Button>),
>,
mut camera_query: Query<&mut Transform, With<Camera>>,
) {
for (interaction, target_camera, RotateCamera(direction)) in &interaction_query {
if let Interaction::Pressed = *interaction {
// Since TargetCamera propagates to the children, we can use it to find
// which side of the screen the button is on.
if let Ok(mut camera_transform) = camera_query.get_mut(target_camera.entity()) {
let angle = match direction {
Direction::Left => -0.1,
Direction::Right => 0.1,
};
camera_transform.rotate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, angle));
}
}
}
}
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut animations: ResMut<Assets<AnimationClip>>,
) {
// Camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
// Light
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 500_000.0,
..default()
},
transform: Transform::from_xyz(0.0, 2.5, 0.0),
..default()
});
// Let's use the `Name` component to target entities. We can use anything we
// like, but names are convenient.
let planet = Name::new("planet");
let orbit_controller = Name::new("orbit_controller");
let satellite = Name::new("satellite");
// Creating the animation
let mut animation = AnimationClip::default();
// A curve can modify a single part of a transform, here the translation
animation.add_curve_to_path(
EntityPath {
parts: vec![planet.clone()],
},
VariableCurve {
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0],
keyframes: Keyframes::Translation(vec![
Vec3::new(1.0, 0.0, 1.0),
Vec3::new(-1.0, 0.0, 1.0),
Vec3::new(-1.0, 0.0, -1.0),
Vec3::new(1.0, 0.0, -1.0),
// in case seamless looping is wanted, the last keyframe should
// be the same as the first one
Vec3::new(1.0, 0.0, 1.0),
]),
interpolation: Interpolation::Linear,
},
);
// Or it can modify the rotation of the transform.
// To find the entity to modify, the hierarchy will be traversed looking for
// an entity with the right name at each level
animation.add_curve_to_path(
EntityPath {
parts: vec![planet.clone(), orbit_controller.clone()],
},
VariableCurve {
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0],
keyframes: Keyframes::Rotation(vec![
Quat::IDENTITY,
Quat::from_axis_angle(Vec3::Y, PI / 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.),
Quat::IDENTITY,
]),
interpolation: Interpolation::Linear,
},
);
// If a curve in an animation is shorter than the other, it will not repeat
// until all other curves are finished. In that case, another animation should
// be created for each part that would have a different duration / period
animation.add_curve_to_path(
EntityPath {
parts: vec![planet.clone(), orbit_controller.clone(), satellite.clone()],
},
VariableCurve {
keyframe_timestamps: vec![0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0],
keyframes: Keyframes::Scale(vec![
Vec3::splat(0.8),
Vec3::splat(1.2),
Vec3::splat(0.8),
Vec3::splat(1.2),
Vec3::splat(0.8),
Vec3::splat(1.2),
Vec3::splat(0.8),
Vec3::splat(1.2),
Vec3::splat(0.8),
]),
interpolation: Interpolation::Linear,
},
);
// There can be more than one curve targeting the same entity path
animation.add_curve_to_path(
EntityPath {
parts: vec![planet.clone(), orbit_controller.clone(), satellite.clone()],
},
VariableCurve {
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0],
keyframes: Keyframes::Rotation(vec![
Quat::IDENTITY,
Quat::from_axis_angle(Vec3::Y, PI / 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.),
Quat::IDENTITY,
]),
interpolation: Interpolation::Linear,
},
);
// Create the animation player, and set it to repeat
let mut player = AnimationPlayer::default();
player.play(animations.add(animation)).repeat();
// Create the scene that will be animated
// First entity is the planet
commands
.spawn((
PbrBundle {
mesh: meshes.add(Sphere::default()),
material: materials.add(Color::rgb(0.8, 0.7, 0.6)),
..default()
},
// Add the Name component, and the animation player
planet,
player,
))
.with_children(|p| {
// This entity is just used for animation, but doesn't display anything
p.spawn((
SpatialBundle::INHERITED_IDENTITY,
// Add the Name component
orbit_controller,
))
.with_children(|p| {
// The satellite, placed at a distance of the planet
p.spawn((
PbrBundle {
transform: Transform::from_xyz(1.5, 0.0, 0.0),
mesh: meshes.add(Cuboid::new(0.5, 0.5, 0.5)),
material: materials.add(Color::rgb(0.3, 0.9, 0.3)),
..default()
},
// Add the Name component
satellite,
));
});
});
}
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.
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?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// circular base
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::rgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// light
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
More examples
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// directional 'sun' light
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: 32000.0,
..default()
},
transform: Transform::from_xyz(0.0, 2.0, 0.0)
.with_rotation(Quat::from_rotation_x(-PI / 4.)),
..default()
});
let skybox_handle = asset_server.load(CUBEMAPS[0].0);
// camera
commands.spawn((
Camera3dBundle {
transform: Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
CameraController::default(),
Skybox {
image: skybox_handle.clone(),
brightness: 1000.0,
},
));
// ambient light
// NOTE: The ambient light is used to scale how bright the environment map is so with a bright
// environment map, use an appropriate color and brightness to match
commands.insert_resource(AmbientLight {
color: Color::rgb_u8(210, 220, 240),
brightness: 1.0,
});
commands.insert_resource(Cubemap {
is_loaded: false,
index: 0,
image_handle: skybox_handle,
});
}
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut images: ResMut<Assets<Image>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let debug_material = materials.add(StandardMaterial {
base_color_texture: Some(images.add(uv_debug_texture())),
..default()
});
let shapes = [
meshes.add(Cuboid::default()),
meshes.add(Capsule3d::default()),
meshes.add(Torus::default()),
meshes.add(Cylinder::default()),
meshes.add(Sphere::default().mesh().ico(5).unwrap()),
meshes.add(Sphere::default().mesh().uv(32, 18)),
];
let num_shapes = shapes.len();
for (i, shape) in shapes.into_iter().enumerate() {
commands.spawn((
PbrBundle {
mesh: shape,
material: debug_material.clone(),
transform: Transform::from_xyz(
-X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
2.0,
0.0,
)
.with_rotation(Quat::from_rotation_x(-PI / 4.)),
..default()
},
Shape,
));
}
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
intensity: 10_000_000.,
range: 100.0,
..default()
},
transform: Transform::from_xyz(8.0, 16.0, 8.0),
..default()
});
// ground plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
material: materials.add(Color::SILVER),
..default()
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 6., 12.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y),
..default()
});
}
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// load a texture and retrieve its aspect ratio
let texture_handle = asset_server.load("branding/bevy_logo_dark_big.png");
let aspect = 0.25;
// create a new quad mesh. this is what we will apply the texture to
let quad_width = 8.0;
let quad_handle = meshes.add(Rectangle::new(quad_width, quad_width * aspect));
// this material renders the texture normally
let material_handle = materials.add(StandardMaterial {
base_color_texture: Some(texture_handle.clone()),
alpha_mode: AlphaMode::Blend,
unlit: true,
..default()
});
// this material modulates the texture to make it red (and slightly transparent)
let red_material_handle = materials.add(StandardMaterial {
base_color: Color::rgba(1.0, 0.0, 0.0, 0.5),
base_color_texture: Some(texture_handle.clone()),
alpha_mode: AlphaMode::Blend,
unlit: true,
..default()
});
// and lets make this one blue! (and also slightly transparent)
let blue_material_handle = materials.add(StandardMaterial {
base_color: Color::rgba(0.0, 0.0, 1.0, 0.5),
base_color_texture: Some(texture_handle),
alpha_mode: AlphaMode::Blend,
unlit: true,
..default()
});
// textured quad - normal
commands.spawn(PbrBundle {
mesh: quad_handle.clone(),
material: material_handle,
transform: Transform::from_xyz(0.0, 0.0, 1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
});
// textured quad - modulated
commands.spawn(PbrBundle {
mesh: quad_handle.clone(),
material: red_material_handle,
transform: Transform::from_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
});
// textured quad - modulated
commands.spawn(PbrBundle {
mesh: quad_handle,
material: blue_material_handle,
transform: Transform::from_xyz(0.0, 0.0, -1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
});
// camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(3.0, 5.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
) {
let size = Extent3d {
width: 512,
height: 512,
..default()
};
// This is the texture that will be rendered to.
let mut image = Image {
texture_descriptor: TextureDescriptor {
label: None,
size,
dimension: TextureDimension::D2,
format: TextureFormat::Bgra8UnormSrgb,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
},
..default()
};
// fill image.data with zeroes
image.resize(size);
let image_handle = images.add(image);
// Light
commands.spawn(DirectionalLightBundle::default());
let texture_camera = commands
.spawn(Camera2dBundle {
camera: Camera {
// render before the "main pass" camera
order: -1,
target: RenderTarget::Image(image_handle.clone()),
..default()
},
..default()
})
.id();
commands
.spawn((
NodeBundle {
style: Style {
// Cover the whole image
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
background_color: Color::GOLD.into(),
..default()
},
TargetCamera(texture_camera),
))
.with_children(|parent| {
parent.spawn(TextBundle::from_section(
"This is a cube",
TextStyle {
font_size: 40.0,
color: Color::BLACK,
..default()
},
));
});
let cube_size = 4.0;
let cube_handle = meshes.add(Cuboid::new(cube_size, cube_size, cube_size));
// This material has the texture that has been rendered.
let material_handle = materials.add(StandardMaterial {
base_color_texture: Some(image_handle),
reflectance: 0.02,
unlit: false,
..default()
});
// Cube with material containing the rendered UI texture.
commands.spawn((
PbrBundle {
mesh: cube_handle,
material: material_handle,
transform: Transform::from_xyz(0.0, 0.0, 1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
},
Cube,
));
// The main pass camera.
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 0.0, 15.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
) {
let size = Extent3d {
width: 512,
height: 512,
..default()
};
// This is the texture that will be rendered to.
let mut image = Image {
texture_descriptor: TextureDescriptor {
label: None,
size,
dimension: TextureDimension::D2,
format: TextureFormat::Bgra8UnormSrgb,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
},
..default()
};
// fill image.data with zeroes
image.resize(size);
let image_handle = images.add(image);
let cube_handle = meshes.add(Cuboid::new(4.0, 4.0, 4.0));
let cube_material_handle = materials.add(StandardMaterial {
base_color: Color::rgb(0.8, 0.7, 0.6),
reflectance: 0.02,
unlit: false,
..default()
});
// This specifies the layer used for the first pass, which will be attached to the first pass camera and cube.
let first_pass_layer = RenderLayers::layer(1);
// The cube that will be rendered to the texture.
commands.spawn((
PbrBundle {
mesh: cube_handle,
material: cube_material_handle,
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
..default()
},
FirstPassCube,
first_pass_layer,
));
// Light
// NOTE: we add the light to all layers so it affects both the rendered-to-texture cube, and the cube on which we display the texture
// Setting the layer to RenderLayers::layer(0) would cause the main view to be lit, but the rendered-to-texture cube to be unlit.
// Setting the layer to RenderLayers::layer(1) would cause the rendered-to-texture cube to be lit, but the main view to be unlit.
commands.spawn((
PointLightBundle {
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
..default()
},
RenderLayers::all(),
));
commands.spawn((
Camera3dBundle {
camera: Camera {
// render before the "main pass" camera
order: -1,
target: image_handle.clone().into(),
clear_color: Color::WHITE.into(),
..default()
},
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0))
.looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
first_pass_layer,
));
let cube_size = 4.0;
let cube_handle = meshes.add(Cuboid::new(cube_size, cube_size, cube_size));
// This material has the texture that has been rendered.
let material_handle = materials.add(StandardMaterial {
base_color_texture: Some(image_handle),
reflectance: 0.02,
unlit: false,
..default()
});
// Main pass cube, with material containing the rendered first pass texture.
commands.spawn((
PbrBundle {
mesh: cube_handle,
material: material_handle,
transform: Transform::from_xyz(0.0, 0.0, 1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
},
MainPassCube,
));
// The main pass camera.
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 0.0, 15.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
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?
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
fn rotate_camera(mut query: Query<&mut Transform, With<Camera>>, time: Res<Time>) {
let mut transform = query.single_mut();
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(time.delta_seconds() / 2.));
}
fn draw_example_collection(
mut gizmos: Gizmos,
mut my_gizmos: Gizmos<MyRoundGizmos>,
time: Res<Time>,
) {
gizmos.cuboid(
Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
Color::BLACK,
);
gizmos.rect(
Vec3::new(time.elapsed_seconds().cos() * 2.5, 1., 0.),
Quat::from_rotation_y(PI / 2.),
Vec2::splat(2.),
Color::GREEN,
);
my_gizmos.sphere(Vec3::new(1., 0.5, 0.), Quat::IDENTITY, 0.5, Color::RED);
for y in [0., 0.5, 1.] {
gizmos.ray(
Vec3::new(1., y, 0.),
Vec3::new(-3., (time.elapsed_seconds() * 3.).sin(), 0.),
Color::BLUE,
);
}
my_gizmos
.arc_3d(
180.0_f32.to_radians(),
0.2,
Vec3::ONE,
Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
Color::ORANGE,
)
.segments(10);
// Circles have 32 line-segments by default.
my_gizmos.circle(Vec3::ZERO, Direction3d::Y, 3., Color::BLACK);
// You may want to increase this for larger circles or spheres.
my_gizmos
.circle(Vec3::ZERO, Direction3d::Y, 3.1, Color::NAVY)
.segments(64);
my_gizmos
.sphere(Vec3::ZERO, Quat::IDENTITY, 3.2, Color::BLACK)
.circle_segments(64);
gizmos.arrow(Vec3::ZERO, Vec3::ONE * 1.5, Color::YELLOW);
}
More examples
199 200 201 202 203 204 205 206 207 208 209 210 211 212
fn rotation(
mut query: Query<&mut Transform, With<Camera>>,
input: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
) {
let mut transform = query.single_mut();
let delta = time.delta_seconds();
if input.pressed(KeyCode::ArrowLeft) {
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(delta));
} else if input.pressed(KeyCode::ArrowRight) {
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(-delta));
}
}
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Spawn a cube to scale.
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_y(PI / 4.0)),
..default()
},
Scaling::new(),
));
// Spawn a camera looking at the entities to show what's happening in this example.
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 10.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
// Add a light source for better 3d visibility.
commands.spawn(DirectionalLightBundle {
transform: Transform::from_xyz(3.0, 3.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Add an object (sphere) for visualizing scaling.
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(3.0).mesh().ico(32).unwrap()),
material: materials.add(Color::YELLOW),
transform: Transform::from_translation(Vec3::ZERO),
..default()
},
Center {
max_size: 1.0,
min_size: 0.1,
scale_factor: 0.05,
},
));
// Add the cube to visualize rotation and translation.
// This cube will circle around the center_sphere
// by changing its rotation each frame and moving forward.
// Define a start transform for an orbiting cube, that's away from our central object (sphere)
// and rotate it so it will be able to move around the sphere and not towards it.
let cube_spawn =
Transform::from_translation(Vec3::Z * -10.0).with_rotation(Quat::from_rotation_y(PI / 2.));
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::WHITE),
transform: cube_spawn,
..default()
},
CubeState {
start_pos: cube_spawn.translation,
move_speed: 2.0,
turn_speed: 0.2,
},
));
// Spawn a camera looking at the entities to show what's happening in this example.
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 10.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
// Add a light source for better 3d visibility.
commands.spawn(DirectionalLightBundle {
transform: Transform::from_xyz(3.0, 3.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
fn example_control_system(
mut materials: ResMut<Assets<StandardMaterial>>,
controllable: Query<(&Handle<StandardMaterial>, &ExampleControls)>,
mut camera: Query<(&mut Camera, &mut Transform, &GlobalTransform), With<Camera3d>>,
mut labels: Query<(&mut Style, &ExampleLabel)>,
mut display: Query<&mut Text, With<ExampleDisplay>>,
labelled: Query<&GlobalTransform>,
mut state: Local<ExampleState>,
time: Res<Time>,
input: Res<ButtonInput<KeyCode>>,
) {
if input.pressed(KeyCode::ArrowUp) {
state.alpha = (state.alpha + time.delta_seconds()).min(1.0);
} else if input.pressed(KeyCode::ArrowDown) {
state.alpha = (state.alpha - time.delta_seconds()).max(0.0);
}
if input.just_pressed(KeyCode::Space) {
state.unlit = !state.unlit;
}
let randomize_colors = input.just_pressed(KeyCode::KeyC);
for (material_handle, controls) in &controllable {
let material = materials.get_mut(material_handle).unwrap();
material.base_color.set_a(state.alpha);
if controls.color && randomize_colors {
material.base_color.set_r(random());
material.base_color.set_g(random());
material.base_color.set_b(random());
}
if controls.unlit {
material.unlit = state.unlit;
}
}
let (mut camera, mut camera_transform, camera_global_transform) = camera.single_mut();
if input.just_pressed(KeyCode::KeyH) {
camera.hdr = !camera.hdr;
}
let rotation = if input.pressed(KeyCode::ArrowLeft) {
time.delta_seconds()
} else if input.pressed(KeyCode::ArrowRight) {
-time.delta_seconds()
} else {
0.0
};
camera_transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(rotation));
for (mut style, label) in &mut labels {
let world_position = labelled.get(label.entity).unwrap().translation() + Vec3::Y;
let viewport_position = camera
.world_to_viewport(camera_global_transform, world_position)
.unwrap();
style.top = Val::Px(viewport_position.y);
style.left = Val::Px(viewport_position.x);
}
let mut display = display.single_mut();
display.sections[0].value = format!(
" HDR: {}\nAlpha: {:.2}",
if camera.hdr { "ON " } else { "OFF" },
state.alpha
);
}
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMut<Game>) {
// reset the game state
game.cake_eaten = 0;
game.score = 0;
game.player.i = BOARD_SIZE_I / 2;
game.player.j = BOARD_SIZE_J / 2;
game.player.move_cooldown = Timer::from_seconds(0.3, TimerMode::Once);
commands.spawn(PointLightBundle {
transform: Transform::from_xyz(4.0, 10.0, 4.0),
point_light: PointLight {
intensity: 2_000_000.0,
shadows_enabled: true,
range: 30.0,
..default()
},
..default()
});
// spawn the game board
let cell_scene = asset_server.load("models/AlienCake/tile.glb#Scene0");
game.board = (0..BOARD_SIZE_J)
.map(|j| {
(0..BOARD_SIZE_I)
.map(|i| {
let height = rand::thread_rng().gen_range(-0.1..0.1);
commands.spawn(SceneBundle {
transform: Transform::from_xyz(i as f32, height - 0.2, j as f32),
scene: cell_scene.clone(),
..default()
});
Cell { height }
})
.collect()
})
.collect();
// spawn the game character
game.player.entity = Some(
commands
.spawn(SceneBundle {
transform: Transform {
translation: Vec3::new(
game.player.i as f32,
game.board[game.player.j][game.player.i].height,
game.player.j as f32,
),
rotation: Quat::from_rotation_y(-PI / 2.),
..default()
},
scene: asset_server.load("models/AlienCake/alien.glb#Scene0"),
..default()
})
.id(),
);
// load the scene for the cake
game.bonus.handle = asset_server.load("models/AlienCake/cakeBirthday.glb#Scene0");
// scoreboard
commands.spawn(
TextBundle::from_section(
"Score:",
TextStyle {
font_size: 40.0,
color: Color::rgb(0.5, 0.5, 1.0),
..default()
},
)
.with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(5.0),
left: Val::Px(5.0),
..default()
}),
);
}
// remove all entities that are not a camera or window
fn teardown(mut commands: Commands, entities: Query<Entity, (Without<Camera>, Without<Window>)>) {
for entity in &entities {
commands.entity(entity).despawn();
}
}
// control the game character
fn move_player(
mut commands: Commands,
keyboard_input: Res<ButtonInput<KeyCode>>,
mut game: ResMut<Game>,
mut transforms: Query<&mut Transform>,
time: Res<Time>,
) {
if game.player.move_cooldown.tick(time.delta()).finished() {
let mut moved = false;
let mut rotation = 0.0;
if keyboard_input.pressed(KeyCode::ArrowUp) {
if game.player.i < BOARD_SIZE_I - 1 {
game.player.i += 1;
}
rotation = -PI / 2.;
moved = true;
}
if keyboard_input.pressed(KeyCode::ArrowDown) {
if game.player.i > 0 {
game.player.i -= 1;
}
rotation = PI / 2.;
moved = true;
}
if keyboard_input.pressed(KeyCode::ArrowRight) {
if game.player.j < BOARD_SIZE_J - 1 {
game.player.j += 1;
}
rotation = PI;
moved = true;
}
if keyboard_input.pressed(KeyCode::ArrowLeft) {
if game.player.j > 0 {
game.player.j -= 1;
}
rotation = 0.0;
moved = true;
}
// move on the board
if moved {
game.player.move_cooldown.reset();
*transforms.get_mut(game.player.entity.unwrap()).unwrap() = Transform {
translation: Vec3::new(
game.player.i as f32,
game.board[game.player.j][game.player.i].height,
game.player.j as f32,
),
rotation: Quat::from_rotation_y(rotation),
..default()
};
}
}
// eat the cake!
if let Some(entity) = game.bonus.entity {
if game.player.i == game.bonus.i && game.player.j == game.bonus.j {
game.score += 2;
game.cake_eaten += 1;
commands.entity(entity).despawn_recursive();
game.bonus.entity = None;
}
}
}
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
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn setup(asset_server: Res<AssetServer>, mut commands: Commands) {
commands.insert_resource(MorphData {
the_wave: asset_server.load("models/animated/MorphStressTest.gltf#Animation2"),
mesh: asset_server.load("models/animated/MorphStressTest.gltf#Mesh0/Primitive0"),
});
commands.spawn(SceneBundle {
scene: asset_server.load("models/animated/MorphStressTest.gltf#Scene0"),
..default()
});
commands.spawn(DirectionalLightBundle {
transform: Transform::from_rotation(Quat::from_rotation_z(PI / 2.0)),
..default()
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(3.0, 2.1, 10.2).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn joint_animation(
time: Res<Time>,
parent_query: Query<&Parent, With<SkinnedMesh>>,
children_query: Query<&Children>,
mut transform_query: Query<&mut Transform>,
) {
// Iter skinned mesh entity
for skinned_mesh_parent in &parent_query {
// Mesh node is the parent of the skinned mesh entity.
let mesh_node_entity = skinned_mesh_parent.get();
// Get `Children` in the mesh node.
let mesh_node_children = children_query.get(mesh_node_entity).unwrap();
// First joint is the second child of the mesh node.
let first_joint_entity = mesh_node_children[1];
// Get `Children` in the first joint.
let first_joint_children = children_query.get(first_joint_entity).unwrap();
// Second joint is the first child of the first joint.
let second_joint_entity = first_joint_children[0];
// Get `Transform` in the second joint.
let mut second_joint_transform = transform_query.get_mut(second_joint_entity).unwrap();
second_joint_transform.rotation =
Quat::from_rotation_z(FRAC_PI_2 * time.elapsed_seconds().sin());
}
}
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?
55 56 57 58 59 60 61 62 63 64 65 66 67
fn animate_light_direction(
time: Res<Time>,
mut query: Query<&mut Transform, With<DirectionalLight>>,
) {
for mut transform in &mut query {
transform.rotation = Quat::from_euler(
EulerRot::ZYX,
0.0,
time.elapsed_seconds() * PI / 5.0,
-FRAC_PI_4,
);
}
}
More examples
148 149 150 151 152 153 154 155 156 157 158 159 160
fn light_sway(time: Res<Time>, mut query: Query<(&mut Transform, &mut SpotLight)>) {
for (mut transform, mut angles) in query.iter_mut() {
transform.rotation = Quat::from_euler(
EulerRot::XYZ,
-FRAC_PI_2 + (time.elapsed_seconds() * 0.67 * 3.0).sin() * 0.5,
(time.elapsed_seconds() * 3.0).sin() * 0.5,
0.0,
);
let angle = ((time.elapsed_seconds() * 1.2).sin() + 1.0) * (FRAC_PI_4 - 0.1);
angles.inner_angle = angle * 0.8;
angles.outer_angle = angle;
}
}
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Insert a resource with the current scene information
commands.insert_resource(Animations(vec![
asset_server.load("models/animated/Fox.glb#Animation2"),
asset_server.load("models/animated/Fox.glb#Animation1"),
asset_server.load("models/animated/Fox.glb#Animation0"),
]));
// Camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(100.0, 100.0, 150.0)
.looking_at(Vec3::new(0.0, 20.0, 0.0), Vec3::Y),
..default()
});
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(500000.0, 500000.0)),
material: materials.add(Color::rgb(0.3, 0.5, 0.3)),
..default()
});
// Light
commands.spawn(DirectionalLightBundle {
transform: Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
directional_light: DirectionalLight {
shadows_enabled: true,
..default()
},
cascade_shadow_config: CascadeShadowConfigBuilder {
first_cascade_far_bound: 200.0,
maximum_distance: 400.0,
..default()
}
.into(),
..default()
});
// Fox
commands.spawn(SceneBundle {
scene: asset_server.load("models/animated/Fox.glb#Scene0"),
..default()
});
println!("Animation controls:");
println!(" - spacebar: play / pause");
println!(" - arrow up / down: speed up / slow down animation playback");
println!(" - arrow left / right: seek backward / forward");
println!(" - digit 1 / 3 / 5: play the animation <digit> times");
println!(" - L: loop the animation forever");
println!(" - return: change animation");
}
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
asset_server: Res<AssetServer>,
) {
commands
.spawn(Camera3dBundle {
camera: Camera {
hdr: true,
..default()
},
transform: Transform::from_xyz(-2.0, 2.0, -2.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
})
.insert(ScreenSpaceAmbientOcclusionBundle::default())
.insert(TemporalAntiAliasBundle::default());
let material = materials.add(StandardMaterial {
base_color: Color::rgb(0.5, 0.5, 0.5),
perceptual_roughness: 1.0,
reflectance: 0.0,
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: material.clone(),
transform: Transform::from_xyz(0.0, 0.0, 1.0),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: material.clone(),
transform: Transform::from_xyz(0.0, -1.0, 0.0),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material,
transform: Transform::from_xyz(1.0, 0.0, 0.0),
..default()
});
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.4).mesh().uv(72, 36)),
material: materials.add(StandardMaterial {
base_color: Color::rgb(0.4, 0.4, 0.4),
perceptual_roughness: 1.0,
reflectance: 0.0,
..default()
}),
..default()
},
SphereMarker,
));
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_rotation(Quat::from_euler(
EulerRot::ZYX,
0.0,
PI * -0.15,
PI * -0.15,
)),
..default()
});
commands.spawn(
TextBundle::from_section(
"",
TextStyle {
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
font_size: 26.0,
..default()
},
)
.with_style(Style {
position_type: PositionType::Absolute,
bottom: Val::Px(10.0),
left: Val::Px(10.0),
..default()
}),
);
}
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let spawn_plane_depth = 500.0f32;
let spawn_height = 2.0;
let sphere_radius = 0.25;
let white_handle = materials.add(StandardMaterial {
base_color: Color::WHITE,
perceptual_roughness: 1.0,
..default()
});
let sphere_handle = meshes.add(Sphere::new(sphere_radius));
// sphere - initially a caster
commands.spawn(PbrBundle {
mesh: sphere_handle.clone(),
material: materials.add(Color::RED),
transform: Transform::from_xyz(-1.0, spawn_height, 0.0),
..default()
});
// sphere - initially not a caster
commands.spawn((
PbrBundle {
mesh: sphere_handle,
material: materials.add(Color::BLUE),
transform: Transform::from_xyz(1.0, spawn_height, 0.0),
..default()
},
NotShadowCaster,
));
// floating plane - initially not a shadow receiver and not a caster
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(20.0, 20.0)),
material: materials.add(Color::GREEN),
transform: Transform::from_xyz(0.0, 1.0, -10.0),
..default()
},
NotShadowCaster,
NotShadowReceiver,
));
// lower ground plane - initially a shadow receiver
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(20.0, 20.0)),
material: white_handle,
..default()
});
println!("Using DirectionalLight");
commands.spawn(PointLightBundle {
transform: Transform::from_xyz(5.0, 5.0, 0.0),
point_light: PointLight {
intensity: 0.0,
range: spawn_plane_depth,
color: Color::WHITE,
shadows_enabled: true,
..default()
},
..default()
});
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: light_consts::lux::OVERCAST_DAY,
shadows_enabled: true,
..default()
},
transform: Transform::from_rotation(Quat::from_euler(
EulerRot::ZYX,
0.0,
PI / 2.,
-PI / 4.,
)),
cascade_shadow_config: CascadeShadowConfigBuilder {
first_cascade_far_bound: 7.0,
maximum_distance: 25.0,
..default()
}
.into(),
..default()
});
// camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-5.0, 5.0, 5.0)
.looking_at(Vec3::new(-1.0, 1.0, 0.0), Vec3::Y),
..default()
});
}
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
asset_server: Res<AssetServer>,
) {
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
material: materials.add(Color::rgb(0.1, 0.2, 0.1)),
..default()
});
let cube_material = materials.add(StandardMaterial {
base_color_texture: Some(images.add(uv_debug_texture())),
..default()
});
// Cubes
for i in 0..5 {
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(0.25, 0.25, 0.25)),
material: cube_material.clone(),
transform: Transform::from_xyz(i as f32 * 0.25 - 1.0, 0.125, -i as f32 * 0.5),
..default()
});
}
// Flight Helmet
commands.spawn(SceneBundle {
scene: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"),
..default()
});
// Light
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: light_consts::lux::FULL_DAYLIGHT,
shadows_enabled: true,
..default()
},
transform: Transform::from_rotation(Quat::from_euler(
EulerRot::ZYX,
0.0,
PI * -0.15,
PI * -0.15,
)),
cascade_shadow_config: CascadeShadowConfigBuilder {
maximum_distance: 3.0,
first_cascade_far_bound: 0.9,
..default()
}
.into(),
..default()
});
// Camera
commands.spawn((
Camera3dBundle {
camera: Camera {
hdr: true,
..default()
},
transform: Transform::from_xyz(0.7, 0.7, 1.0)
.looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
..default()
},
ContrastAdaptiveSharpeningSettings {
enabled: false,
..default()
},
EnvironmentMapLight {
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
intensity: 150.0,
},
FogSettings {
color: Color::rgba_u8(43, 44, 47, 255),
falloff: FogFalloff::Linear {
start: 1.0,
end: 4.0,
},
..default()
},
));
// example instructions
commands.spawn(
TextBundle::from_section(
"",
TextStyle {
font_size: 20.,
..default()
},
)
.with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
}),
);
}
sourcepub fn from_mat3(mat: &Mat3) -> Quat
pub fn from_mat3(mat: &Mat3) -> Quat
Creates a quaternion from a 3x3 rotation matrix.
Examples found in repository?
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
fn rotate_primitive_2d_meshes(
mut primitives_2d: Query<
(&mut Transform, &ViewVisibility),
(With<PrimitiveData>, With<MeshDim2>),
>,
time: Res<Time>,
) {
let rotation_2d = Quat::from_mat3(&Mat3::from_angle(time.elapsed_seconds()));
primitives_2d
.iter_mut()
.filter(|(_, vis)| vis.get())
.for_each(|(mut transform, _)| {
transform.rotation = rotation_2d;
});
}
sourcepub fn from_mat3a(mat: &Mat3A) -> Quat
pub fn from_mat3a(mat: &Mat3A) -> Quat
Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
sourcepub fn from_mat4(mat: &Mat4) -> Quat
pub fn from_mat4(mat: &Mat4) -> Quat
Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
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?
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
fn rotate_primitive_3d_meshes(
mut primitives_3d: Query<
(&mut Transform, &ViewVisibility),
(With<PrimitiveData>, With<MeshDim3>),
>,
time: Res<Time>,
) {
let rotation_3d = Quat::from_rotation_arc(
Vec3::Z,
Vec3::new(
time.elapsed_seconds().sin(),
time.elapsed_seconds().cos(),
time.elapsed_seconds().sin() * 0.5,
)
.try_normalize()
.unwrap_or(Vec3::Z),
);
primitives_3d
.iter_mut()
.filter(|(_, vis)| vis.get())
.for_each(|(mut transform, _)| {
transform.rotation = rotation_3d;
});
}
fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
let rotation = Quat::from_rotation_arc(
Vec3::Z,
Vec3::new(
time.elapsed_seconds().sin(),
time.elapsed_seconds().cos(),
time.elapsed_seconds().sin() * 0.5,
)
.try_normalize()
.unwrap_or(Vec3::Z),
);
let color = Color::WHITE;
let segments = 10;
match state.get() {
PrimitiveSelected::RectangleAndCuboid => {
gizmos.primitive_3d(CUBOID, POSITION, rotation, color);
}
PrimitiveSelected::CircleAndSphere => drop(
gizmos
.primitive_3d(SPHERE, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Ellipse => {}
PrimitiveSelected::Triangle => {}
PrimitiveSelected::Plane => drop(gizmos.primitive_3d(PLANE_3D, POSITION, rotation, color)),
PrimitiveSelected::Line => gizmos.primitive_3d(LINE3D, POSITION, rotation, color),
PrimitiveSelected::Segment => gizmos.primitive_3d(SEGMENT_3D, POSITION, rotation, color),
PrimitiveSelected::Polyline => gizmos.primitive_3d(POLYLINE_3D, POSITION, rotation, color),
PrimitiveSelected::Polygon => {}
PrimitiveSelected::RegularPolygon => {}
PrimitiveSelected::Capsule => drop(
gizmos
.primitive_3d(CAPSULE_3D, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Cylinder => drop(
gizmos
.primitive_3d(CYLINDER, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Cone => drop(
gizmos
.primitive_3d(CONE, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::ConicalFrustrum => {
gizmos.primitive_3d(CONICAL_FRUSTRUM, POSITION, rotation, color);
}
PrimitiveSelected::Torus => drop(
gizmos
.primitive_3d(TORUS, POSITION, rotation, color)
.minor_segments(segments)
.major_segments(segments),
),
}
}
More examples
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
fn snap_to_player_system(
mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
player_query: Query<&Transform, With<Player>>,
) {
let player_transform = player_query.single();
// get the player translation in 2D
let player_translation = player_transform.translation.xy();
for mut enemy_transform in &mut query {
// get the vector from the enemy ship to the player ship in 2D and normalize it.
let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
// get the quaternion to rotate from the initial enemy facing direction to the direction
// facing the player
let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));
// rotate the enemy to face the player
enemy_transform.rotation = rotate_to_player;
}
}
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
fn draw_example_collection(
mut gizmos: Gizmos,
mut my_gizmos: Gizmos<MyRoundGizmos>,
time: Res<Time>,
) {
gizmos.cuboid(
Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
Color::BLACK,
);
gizmos.rect(
Vec3::new(time.elapsed_seconds().cos() * 2.5, 1., 0.),
Quat::from_rotation_y(PI / 2.),
Vec2::splat(2.),
Color::GREEN,
);
my_gizmos.sphere(Vec3::new(1., 0.5, 0.), Quat::IDENTITY, 0.5, Color::RED);
for y in [0., 0.5, 1.] {
gizmos.ray(
Vec3::new(1., y, 0.),
Vec3::new(-3., (time.elapsed_seconds() * 3.).sin(), 0.),
Color::BLUE,
);
}
my_gizmos
.arc_3d(
180.0_f32.to_radians(),
0.2,
Vec3::ONE,
Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
Color::ORANGE,
)
.segments(10);
// Circles have 32 line-segments by default.
my_gizmos.circle(Vec3::ZERO, Direction3d::Y, 3., Color::BLACK);
// You may want to increase this for larger circles or spheres.
my_gizmos
.circle(Vec3::ZERO, Direction3d::Y, 3.1, Color::NAVY)
.segments(64);
my_gizmos
.sphere(Vec3::ZERO, Quat::IDENTITY, 3.2, Color::BLACK)
.circle_segments(64);
gizmos.arrow(Vec3::ZERO, Vec3::ONE * 1.5, Color::YELLOW);
}
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.
sourcepub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32)
pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32)
Returns the rotation angles for the given euler rotation sequence.
Examples found in repository?
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
fn render_shapes(mut gizmos: Gizmos, query: Query<(&Shape, &Transform)>) {
let color = Color::GRAY;
for (shape, transform) in query.iter() {
let translation = transform.translation.xy();
let rotation = transform.rotation.to_euler(EulerRot::YXZ).2;
match shape {
Shape::Rectangle(r) => {
gizmos.primitive_2d(*r, translation, rotation, color);
}
Shape::Circle(c) => {
gizmos.primitive_2d(*c, translation, rotation, color);
}
Shape::Triangle(t) => {
gizmos.primitive_2d(*t, translation, rotation, color);
}
Shape::Line(l) => {
gizmos.primitive_2d(*l, translation, rotation, color);
}
Shape::Capsule(c) => {
gizmos.primitive_2d(*c, translation, rotation, color);
}
Shape::Polygon(p) => {
gizmos.primitive_2d(*p, translation, rotation, color);
}
}
}
}
#[derive(Component)]
enum DesiredVolume {
Aabb,
Circle,
}
#[derive(Component, Debug)]
enum CurrentVolume {
Aabb(Aabb2d),
Circle(BoundingCircle),
}
fn update_volumes(
mut commands: Commands,
query: Query<
(Entity, &DesiredVolume, &Shape, &Transform),
Or<(Changed<DesiredVolume>, Changed<Shape>, Changed<Transform>)>,
>,
) {
for (entity, desired_volume, shape, transform) in query.iter() {
let translation = transform.translation.xy();
let rotation = transform.rotation.to_euler(EulerRot::YXZ).2;
match desired_volume {
DesiredVolume::Aabb => {
let aabb = match shape {
Shape::Rectangle(r) => r.aabb_2d(translation, rotation),
Shape::Circle(c) => c.aabb_2d(translation, rotation),
Shape::Triangle(t) => t.aabb_2d(translation, rotation),
Shape::Line(l) => l.aabb_2d(translation, rotation),
Shape::Capsule(c) => c.aabb_2d(translation, rotation),
Shape::Polygon(p) => p.aabb_2d(translation, rotation),
};
commands.entity(entity).insert(CurrentVolume::Aabb(aabb));
}
DesiredVolume::Circle => {
let circle = match shape {
Shape::Rectangle(r) => r.bounding_circle(translation, rotation),
Shape::Circle(c) => c.bounding_circle(translation, rotation),
Shape::Triangle(t) => t.bounding_circle(translation, rotation),
Shape::Line(l) => l.bounding_circle(translation, rotation),
Shape::Capsule(c) => c.bounding_circle(translation, rotation),
Shape::Polygon(p) => p.bounding_circle(translation, rotation),
};
commands
.entity(entity)
.insert(CurrentVolume::Circle(circle));
}
}
}
}
More examples
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
fn run_camera_controller(
time: Res<Time>,
mut windows: Query<&mut Window>,
mut mouse_events: EventReader<MouseMotion>,
mouse_button_input: Res<ButtonInput<MouseButton>>,
key_input: Res<ButtonInput<KeyCode>>,
mut toggle_cursor_grab: Local<bool>,
mut mouse_cursor_grab: Local<bool>,
mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>,
) {
let dt = time.delta_seconds();
if let Ok((mut transform, mut controller)) = query.get_single_mut() {
if !controller.initialized {
let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
controller.yaw = yaw;
controller.pitch = pitch;
controller.initialized = true;
info!("{}", *controller);
}
if !controller.enabled {
mouse_events.clear();
return;
}
// Handle key input
let mut axis_input = Vec3::ZERO;
if key_input.pressed(controller.key_forward) {
axis_input.z += 1.0;
}
if key_input.pressed(controller.key_back) {
axis_input.z -= 1.0;
}
if key_input.pressed(controller.key_right) {
axis_input.x += 1.0;
}
if key_input.pressed(controller.key_left) {
axis_input.x -= 1.0;
}
if key_input.pressed(controller.key_up) {
axis_input.y += 1.0;
}
if key_input.pressed(controller.key_down) {
axis_input.y -= 1.0;
}
let mut cursor_grab_change = false;
if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
*toggle_cursor_grab = !*toggle_cursor_grab;
cursor_grab_change = true;
}
if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = true;
cursor_grab_change = true;
}
if mouse_button_input.just_released(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = false;
cursor_grab_change = true;
}
let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab;
// Apply movement update
if axis_input != Vec3::ZERO {
let max_speed = if key_input.pressed(controller.key_run) {
controller.run_speed
} else {
controller.walk_speed
};
controller.velocity = axis_input.normalize() * max_speed;
} else {
let friction = controller.friction.clamp(0.0, 1.0);
controller.velocity *= 1.0 - friction;
if controller.velocity.length_squared() < 1e-6 {
controller.velocity = Vec3::ZERO;
}
}
let forward = *transform.forward();
let right = *transform.right();
transform.translation += controller.velocity.x * dt * right
+ controller.velocity.y * dt * Vec3::Y
+ controller.velocity.z * dt * forward;
// Handle cursor grab
if cursor_grab_change {
if cursor_grab {
for mut window in &mut windows {
if !window.focused {
continue;
}
window.cursor.grab_mode = CursorGrabMode::Locked;
window.cursor.visible = false;
}
} else {
for mut window in &mut windows {
window.cursor.grab_mode = CursorGrabMode::None;
window.cursor.visible = true;
}
}
}
// Handle mouse input
let mut mouse_delta = Vec2::ZERO;
if cursor_grab {
for mouse_event in mouse_events.read() {
mouse_delta += mouse_event.delta;
}
} else {
mouse_events.clear();
}
if mouse_delta != Vec2::ZERO {
// Apply look update
controller.pitch = (controller.pitch
- mouse_delta.y * RADIANS_PER_DOT * controller.sensitivity)
.clamp(-PI / 2., PI / 2.);
controller.yaw -= mouse_delta.x * RADIANS_PER_DOT * controller.sensitivity;
transform.rotation =
Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
}
}
}
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
.
pub fn is_nan(self) -> bool
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.
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?
154 155 156 157 158 159 160 161 162 163 164 165
fn look_at_star(
mut camera: Query<&mut Transform, (With<Camera>, Without<Star>)>,
star: Query<&Transform, With<Star>>,
) {
let mut camera = camera.single_mut();
let star = star.single();
let new_rotation = camera
.looking_at(star.translation, Vec3::Y)
.rotation
.lerp(camera.rotation, 0.1);
camera.rotation = new_rotation;
}
More examples
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
fn rotate_cube(
mut cubes: Query<(&mut Transform, &mut CubeState), Without<Center>>,
center_spheres: Query<&Transform, With<Center>>,
timer: Res<Time>,
) {
// Calculate the point to circle around. (The position of the center_sphere)
let mut center: Vec3 = Vec3::ZERO;
for sphere in ¢er_spheres {
center += sphere.translation;
}
// Update the rotation of the cube(s).
for (mut transform, cube) in &mut cubes {
// Calculate the rotation of the cube if it would be looking at the sphere in the center.
let look_at_sphere = transform.looking_at(center, *transform.local_y());
// Interpolate between the current rotation and the fully turned rotation
// when looking a the sphere, with a given turn speed to get a smooth motion.
// With higher speed the curvature of the orbit would be smaller.
let incremental_turn_weight = cube.turn_speed * timer.delta_seconds();
let old_rotation = transform.rotation;
transform.rotation = old_rotation.lerp(look_at_sphere.rotation, incremental_turn_weight);
}
}
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?
186 187 188 189 190 191 192 193 194 195 196 197 198
fn move_camera(
mut camera: Query<&mut Transform, With<CameraController>>,
mut current_view: Local<usize>,
button: Res<ButtonInput<MouseButton>>,
) {
let mut camera = camera.single_mut();
if button.just_pressed(MouseButton::Left) {
*current_view = (*current_view + 1) % CAMERA_POSITIONS.len();
}
let target = CAMERA_POSITIONS[*current_view];
camera.translation = camera.translation.lerp(target.translation, 0.2);
camera.rotation = camera.rotation.slerp(target.rotation, 0.2);
}
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.
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: &Affine3A) -> Quat
pub fn from_affine3(a: &Affine3A) -> Quat
Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
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
pub fn as_f64(self) -> DQuat
Trait Implementations§
source§impl Add for Quat
impl Add for Quat
source§impl Animatable for Quat
impl Animatable for Quat
source§fn interpolate(a: &Quat, b: &Quat, t: f32) -> Quat
fn interpolate(a: &Quat, b: &Quat, t: f32) -> Quat
Performs an nlerp, because it’s cheaper and easier to combine with other animations, reference: http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
source§fn blend(inputs: impl Iterator<Item = BlendInput<Quat>>) -> Quat
fn blend(inputs: impl Iterator<Item = BlendInput<Quat>>) -> Quat
source§fn post_process(&mut self, _world: &World)
fn post_process(&mut self, _world: &World)
World
.
Most animatable types do not need to implement this.source§impl<'de> Deserialize<'de> for Quat
impl<'de> Deserialize<'de> for Quat
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 FromReflect for Quat
impl FromReflect for Quat
source§fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<Quat>
fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<Quat>
Self
from a reflected value.source§fn take_from_reflect(
reflect: Box<dyn Reflect>
) -> Result<Self, Box<dyn Reflect>>
fn take_from_reflect( reflect: Box<dyn Reflect> ) -> Result<Self, Box<dyn Reflect>>
Self
using,
constructing the value using from_reflect
if that fails. Read moresource§impl GetTypeRegistration for Quat
impl GetTypeRegistration for Quat
source§impl Mul<Direction3d> for Quat
impl Mul<Direction3d> for Quat
source§fn mul(self, direction: Direction3d) -> <Quat as Mul<Direction3d>>::Output
fn mul(self, direction: Direction3d) -> <Quat as Mul<Direction3d>>::Output
Rotates the Direction3d
using a Quat
.
§type Output = Direction3d
type Output = Direction3d
*
operator.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 Reflect for Quat
impl Reflect for Quat
source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any
.source§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§fn clone_value(&self) -> Box<dyn Reflect>
fn clone_value(&self) -> Box<dyn Reflect>
Reflect
trait object. Read moresource§fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>
source§fn apply(&mut self, value: &(dyn Reflect + 'static))
fn apply(&mut self, value: &(dyn Reflect + 'static))
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 reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>
fn reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>
source§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
source§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
source§fn serializable(&self) -> Option<Serializable<'_>>
fn serializable(&self) -> Option<Serializable<'_>>
source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
source§impl Serialize for Quat
impl Serialize for Quat
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 Struct for Quat
impl Struct for Quat
source§fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
name
as a &dyn Reflect
.source§fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
name
as a
&mut dyn Reflect
.source§fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
index
as a
&dyn Reflect
.source§fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
index
as a &mut dyn Reflect
.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<'_> ⓘ
source§fn clone_dynamic(&self) -> DynamicStruct
fn clone_dynamic(&self) -> DynamicStruct
DynamicStruct
.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<Image>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> 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,
§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> 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> 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<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
Self
using data from the given World
.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 Reflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p> ) -> Result<&(dyn Reflect + 'static), ReflectPathError<'p>>
path
. Read moresource§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p> ) -> Result<&mut (dyn Reflect + '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 more