#[repr(C)]pub struct Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
Expand description
A 3-dimensional vector.
Fields§
§x: f32
§y: f32
§z: f32
Implementations§
Source§impl Vec3
impl Vec3
Sourcepub const NEG_INFINITY: Vec3
pub const NEG_INFINITY: Vec3
All f32::NEG_INFINITY
.
Sourcepub const fn new(x: f32, y: f32, z: f32) -> Vec3
pub const fn new(x: f32, y: f32, z: f32) -> Vec3
Creates a new vector.
Examples found in repository?
46const DISTANCE_BETWEEN_SHAPES: Vec3 = Vec3::new(2.0, 0.0, 0.0);
47
48/// Maximum amount of points allowed to be present.
49/// Should be set such that it does not cause large amounts of lag when reached.
50const MAX_POINTS: usize = 3000; // TODO: Test wasm and add a wasm-specific-bound
51
52/// How many points should be spawned each frame
53const POINTS_PER_FRAME: usize = 3;
54
55/// Color used for the inside points
56const INSIDE_POINT_COLOR: LinearRgba = LinearRgba::rgb(0.855, 1.1, 0.01);
57/// Color used for the points on the boundary
58const BOUNDARY_POINT_COLOR: LinearRgba = LinearRgba::rgb(0.08, 0.2, 0.90);
59
60/// Time (in seconds) for the spawning/despawning animation
61const ANIMATION_TIME: f32 = 1.0;
62
63/// Color for the sky and the sky-light
64const SKY_COLOR: Color = Color::srgb(0.02, 0.06, 0.15);
65
66const SMALL_3D: f32 = 0.5;
67const BIG_3D: f32 = 1.0;
68
69// primitives
70
71const CUBOID: Cuboid = Cuboid {
72 half_size: Vec3::new(SMALL_3D, BIG_3D, SMALL_3D),
73};
74
75const SPHERE: Sphere = Sphere {
76 radius: 1.5 * SMALL_3D,
77};
78
79const TRIANGLE_3D: Triangle3d = Triangle3d {
80 vertices: [
81 Vec3::new(BIG_3D, -BIG_3D * 0.5, 0.0),
82 Vec3::new(0.0, BIG_3D, 0.0),
83 Vec3::new(-BIG_3D, -BIG_3D * 0.5, 0.0),
84 ],
85};
86
87const CAPSULE_3D: Capsule3d = Capsule3d {
88 radius: SMALL_3D,
89 half_length: SMALL_3D,
90};
91
92const CYLINDER: Cylinder = Cylinder {
93 radius: SMALL_3D,
94 half_height: SMALL_3D,
95};
96
97const TETRAHEDRON: Tetrahedron = Tetrahedron {
98 vertices: [
99 Vec3::new(-BIG_3D, -BIG_3D * 0.67, BIG_3D * 0.5),
100 Vec3::new(BIG_3D, -BIG_3D * 0.67, BIG_3D * 0.5),
101 Vec3::new(0.0, -BIG_3D * 0.67, -BIG_3D * 1.17),
102 Vec3::new(0.0, BIG_3D, 0.0),
103 ],
104};
More examples
21const BALL_STARTING_POSITION: Vec3 = Vec3::new(0.0, -50.0, 1.0);
22const BALL_DIAMETER: f32 = 30.;
23const BALL_SPEED: f32 = 400.0;
24const INITIAL_BALL_DIRECTION: Vec2 = Vec2::new(0.5, -0.5);
25
26const WALL_THICKNESS: f32 = 10.0;
27// x coordinates
28const LEFT_WALL: f32 = -450.;
29const RIGHT_WALL: f32 = 450.;
30// y coordinates
31const BOTTOM_WALL: f32 = -300.;
32const TOP_WALL: f32 = 300.;
33
34const BRICK_SIZE: Vec2 = Vec2::new(100., 30.);
35// These values are exact
36const GAP_BETWEEN_PADDLE_AND_BRICKS: f32 = 270.0;
37const GAP_BETWEEN_BRICKS: f32 = 5.0;
38// These values are lower bounds, as the number of bricks is computed
39const GAP_BETWEEN_BRICKS_AND_CEILING: f32 = 20.0;
40const GAP_BETWEEN_BRICKS_AND_SIDES: f32 = 20.0;
41
42const SCOREBOARD_FONT_SIZE: f32 = 33.0;
43const SCOREBOARD_TEXT_PADDING: Val = Val::Px(5.0);
44
45const BACKGROUND_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
46const PADDLE_COLOR: Color = Color::srgb(0.3, 0.3, 0.7);
47const BALL_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
48const BRICK_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
49const WALL_COLOR: Color = Color::srgb(0.8, 0.8, 0.8);
50const TEXT_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
51const SCORE_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
52
53fn main() {
54 App::new()
55 .add_plugins(DefaultPlugins)
56 .add_plugins(
57 stepping::SteppingPlugin::default()
58 .add_schedule(Update)
59 .add_schedule(FixedUpdate)
60 .at(Val::Percent(35.0), Val::Percent(50.0)),
61 )
62 .insert_resource(Score(0))
63 .insert_resource(ClearColor(BACKGROUND_COLOR))
64 .add_event::<CollisionEvent>()
65 .add_systems(Startup, setup)
66 // Add our gameplay simulation systems to the fixed timestep schedule
67 // which runs at 64 Hz by default
68 .add_systems(
69 FixedUpdate,
70 (
71 apply_velocity,
72 move_paddle,
73 check_for_collisions,
74 play_collision_sound,
75 )
76 // `chain`ing systems together runs them in order
77 .chain(),
78 )
79 .add_systems(Update, update_scoreboard)
80 .run();
81}
82
83#[derive(Component)]
84struct Paddle;
85
86#[derive(Component)]
87struct Ball;
88
89#[derive(Component, Deref, DerefMut)]
90struct Velocity(Vec2);
91
92#[derive(Component)]
93struct Collider;
94
95#[derive(Event, Default)]
96struct CollisionEvent;
97
98#[derive(Component)]
99struct Brick;
100
101#[derive(Resource, Deref)]
102struct CollisionSound(Handle<AudioSource>);
103
104// This bundle is a collection of the components that define a "wall" in our game
105#[derive(Bundle)]
106struct WallBundle {
107 // You can nest bundles inside of other bundles like this
108 // Allowing you to compose their functionality
109 sprite: Sprite,
110 transform: Transform,
111 collider: Collider,
112}
113
114/// Which side of the arena is this wall located on?
115enum WallLocation {
116 Left,
117 Right,
118 Bottom,
119 Top,
120}
121
122impl WallLocation {
123 /// Location of the *center* of the wall, used in `transform.translation()`
124 fn position(&self) -> Vec2 {
125 match self {
126 WallLocation::Left => Vec2::new(LEFT_WALL, 0.),
127 WallLocation::Right => Vec2::new(RIGHT_WALL, 0.),
128 WallLocation::Bottom => Vec2::new(0., BOTTOM_WALL),
129 WallLocation::Top => Vec2::new(0., TOP_WALL),
130 }
131 }
132
133 /// (x, y) dimensions of the wall, used in `transform.scale()`
134 fn size(&self) -> Vec2 {
135 let arena_height = TOP_WALL - BOTTOM_WALL;
136 let arena_width = RIGHT_WALL - LEFT_WALL;
137 // Make sure we haven't messed up our constants
138 assert!(arena_height > 0.0);
139 assert!(arena_width > 0.0);
140
141 match self {
142 WallLocation::Left | WallLocation::Right => {
143 Vec2::new(WALL_THICKNESS, arena_height + WALL_THICKNESS)
144 }
145 WallLocation::Bottom | WallLocation::Top => {
146 Vec2::new(arena_width + WALL_THICKNESS, WALL_THICKNESS)
147 }
148 }
149 }
150}
151
152impl WallBundle {
153 // This "builder method" allows us to reuse logic across our wall entities,
154 // making our code easier to read and less prone to bugs when we change the logic
155 fn new(location: WallLocation) -> WallBundle {
156 WallBundle {
157 sprite: Sprite::from_color(WALL_COLOR, Vec2::ONE),
158 transform: Transform {
159 // We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
160 // This is used to determine the order of our sprites
161 translation: location.position().extend(0.0),
162 // The z-scale of 2D objects must always be 1.0,
163 // or their ordering will be affected in surprising ways.
164 // See https://github.com/bevyengine/bevy/issues/4149
165 scale: location.size().extend(1.0),
166 ..default()
167 },
168 collider: Collider,
169 }
170 }
171}
172
173// This resource tracks the game's score
174#[derive(Resource, Deref, DerefMut)]
175struct Score(usize);
176
177#[derive(Component)]
178struct ScoreboardUi;
179
180// Add the game's entities to our world
181fn setup(
182 mut commands: Commands,
183 mut meshes: ResMut<Assets<Mesh>>,
184 mut materials: ResMut<Assets<ColorMaterial>>,
185 asset_server: Res<AssetServer>,
186) {
187 // Camera
188 commands.spawn(Camera2d);
189
190 // Sound
191 let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
192 commands.insert_resource(CollisionSound(ball_collision_sound));
193
194 // Paddle
195 let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
196
197 commands.spawn((
198 Sprite::from_color(PADDLE_COLOR, Vec2::ONE),
199 Transform {
200 translation: Vec3::new(0.0, paddle_y, 0.0),
201 scale: PADDLE_SIZE.extend(1.0),
202 ..default()
203 },
204 Paddle,
205 Collider,
206 ));
207
208 // Ball
209 commands.spawn((
210 Mesh2d(meshes.add(Circle::default())),
211 MeshMaterial2d(materials.add(BALL_COLOR)),
212 Transform::from_translation(BALL_STARTING_POSITION)
213 .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
214 Ball,
215 Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
216 ));
217
218 // Scoreboard
219 commands
220 .spawn((
221 Text::new("Score: "),
222 TextFont {
223 font_size: SCOREBOARD_FONT_SIZE,
224 ..default()
225 },
226 TextColor(TEXT_COLOR),
227 ScoreboardUi,
228 Node {
229 position_type: PositionType::Absolute,
230 top: SCOREBOARD_TEXT_PADDING,
231 left: SCOREBOARD_TEXT_PADDING,
232 ..default()
233 },
234 ))
235 .with_child((
236 TextSpan::default(),
237 TextFont {
238 font_size: SCOREBOARD_FONT_SIZE,
239 ..default()
240 },
241 TextColor(SCORE_COLOR),
242 ));
243
244 // Walls
245 commands.spawn(WallBundle::new(WallLocation::Left));
246 commands.spawn(WallBundle::new(WallLocation::Right));
247 commands.spawn(WallBundle::new(WallLocation::Bottom));
248 commands.spawn(WallBundle::new(WallLocation::Top));
249
250 // Bricks
251 let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
252 let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
253 let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;
254
255 assert!(total_width_of_bricks > 0.0);
256 assert!(total_height_of_bricks > 0.0);
257
258 // Given the space available, compute how many rows and columns of bricks we can fit
259 let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
260 let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
261 let n_vertical_gaps = n_columns - 1;
262
263 // Because we need to round the number of columns,
264 // the space on the top and sides of the bricks only captures a lower bound, not an exact value
265 let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
266 let left_edge_of_bricks = center_of_bricks
267 // Space taken up by the bricks
268 - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
269 // Space taken up by the gaps
270 - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;
271
272 // In Bevy, the `translation` of an entity describes the center point,
273 // not its bottom-left corner
274 let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
275 let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;
276
277 for row in 0..n_rows {
278 for column in 0..n_columns {
279 let brick_position = Vec2::new(
280 offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
281 offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
282 );
283
284 // brick
285 commands.spawn((
286 Sprite {
287 color: BRICK_COLOR,
288 ..default()
289 },
290 Transform {
291 translation: brick_position.extend(0.0),
292 scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
293 ..default()
294 },
295 Brick,
296 Collider,
297 ));
298 }
299 }
300}
154const CUBOID: Cuboid = Cuboid {
155 half_size: Vec3::new(BIG_3D, SMALL_3D, BIG_3D),
156};
157
158const CIRCLE: Circle = Circle { radius: BIG_2D };
159const SPHERE: Sphere = Sphere { radius: BIG_3D };
160
161const ELLIPSE: Ellipse = Ellipse {
162 half_size: Vec2::new(BIG_2D, SMALL_2D),
163};
164
165const TRIANGLE_2D: Triangle2d = Triangle2d {
166 vertices: [
167 Vec2::new(BIG_2D, 0.0),
168 Vec2::new(0.0, BIG_2D),
169 Vec2::new(-BIG_2D, 0.0),
170 ],
171};
172
173const TRIANGLE_3D: Triangle3d = Triangle3d {
174 vertices: [
175 Vec3::new(BIG_3D, 0.0, 0.0),
176 Vec3::new(0.0, BIG_3D, 0.0),
177 Vec3::new(-BIG_3D, 0.0, 0.0),
178 ],
179};
180
181const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
182const PLANE_3D: Plane3d = Plane3d {
183 normal: Dir3::Y,
184 half_size: Vec2::new(BIG_3D, BIG_3D),
185};
186
187const LINE2D: Line2d = Line2d { direction: Dir2::X };
188const LINE3D: Line3d = Line3d { direction: Dir3::X };
189
190const SEGMENT_2D: Segment2d = Segment2d {
191 direction: Dir2::X,
192 half_length: BIG_2D,
193};
194const SEGMENT_3D: Segment3d = Segment3d {
195 direction: Dir3::X,
196 half_length: BIG_3D,
197};
198
199const POLYLINE_2D: Polyline2d<4> = Polyline2d {
200 vertices: [
201 Vec2::new(-BIG_2D, -SMALL_2D),
202 Vec2::new(-SMALL_2D, SMALL_2D),
203 Vec2::new(SMALL_2D, -SMALL_2D),
204 Vec2::new(BIG_2D, SMALL_2D),
205 ],
206};
207const POLYLINE_3D: Polyline3d<4> = Polyline3d {
208 vertices: [
209 Vec3::new(-BIG_3D, -SMALL_3D, -SMALL_3D),
210 Vec3::new(SMALL_3D, SMALL_3D, 0.0),
211 Vec3::new(-SMALL_3D, -SMALL_3D, 0.0),
212 Vec3::new(BIG_3D, SMALL_3D, SMALL_3D),
213 ],
214};
215
216const POLYGON_2D: Polygon<5> = Polygon {
217 vertices: [
218 Vec2::new(-BIG_2D, -SMALL_2D),
219 Vec2::new(BIG_2D, -SMALL_2D),
220 Vec2::new(BIG_2D, SMALL_2D),
221 Vec2::new(0.0, 0.0),
222 Vec2::new(-BIG_2D, SMALL_2D),
223 ],
224};
225
226const REGULAR_POLYGON: RegularPolygon = RegularPolygon {
227 circumcircle: Circle { radius: BIG_2D },
228 sides: 5,
229};
230
231const CAPSULE_2D: Capsule2d = Capsule2d {
232 radius: SMALL_2D,
233 half_length: SMALL_2D,
234};
235const CAPSULE_3D: Capsule3d = Capsule3d {
236 radius: SMALL_3D,
237 half_length: SMALL_3D,
238};
239
240const CYLINDER: Cylinder = Cylinder {
241 radius: SMALL_3D,
242 half_height: SMALL_3D,
243};
244
245const CONE: Cone = Cone {
246 radius: BIG_3D,
247 height: BIG_3D,
248};
249
250const CONICAL_FRUSTUM: ConicalFrustum = ConicalFrustum {
251 radius_top: BIG_3D,
252 radius_bottom: SMALL_3D,
253 height: BIG_3D,
254};
255
256const ANNULUS: Annulus = Annulus {
257 inner_circle: Circle { radius: SMALL_2D },
258 outer_circle: Circle { radius: BIG_2D },
259};
260
261const TORUS: Torus = Torus {
262 minor_radius: SMALL_3D / 2.0,
263 major_radius: SMALL_3D * 1.5,
264};
265
266const TETRAHEDRON: Tetrahedron = Tetrahedron {
267 vertices: [
268 Vec3::new(-BIG_3D, 0.0, 0.0),
269 Vec3::new(BIG_3D, 0.0, 0.0),
270 Vec3::new(0.0, 0.0, -BIG_3D * 1.67),
271 Vec3::new(0.0, BIG_3D * 1.67, -BIG_3D * 0.5),
272 ],
273};
274
275const ARC: Arc2d = Arc2d {
276 radius: BIG_2D,
277 half_angle: std::f32::consts::FRAC_PI_4,
278};
279
280const CIRCULAR_SECTOR: CircularSector = CircularSector {
281 arc: Arc2d {
282 radius: BIG_2D,
283 half_angle: std::f32::consts::FRAC_PI_4,
284 },
285};
286
287const CIRCULAR_SEGMENT: CircularSegment = CircularSegment {
288 arc: Arc2d {
289 radius: BIG_2D,
290 half_angle: std::f32::consts::FRAC_PI_4,
291 },
292};
293
294fn setup_cameras(mut commands: Commands) {
295 let start_in_2d = true;
296 let make_camera = |is_active| Camera {
297 is_active,
298 ..Default::default()
299 };
300
301 commands.spawn((Camera2d, make_camera(start_in_2d)));
302
303 commands.spawn((
304 Camera3d::default(),
305 make_camera(!start_in_2d),
306 Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
307 ));
308}
309
310fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
311 ambient_light.brightness = 50.0;
312}
313
314fn setup_lights(mut commands: Commands) {
315 commands.spawn((
316 PointLight {
317 intensity: 5000.0,
318 ..default()
319 },
320 Transform::from_translation(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 2.0, 0.0))
321 .looking_at(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0), Vec3::Y),
322 ));
323}
324
325/// Marker component for header text
326#[derive(Debug, Clone, Component, Default, Reflect)]
327pub struct HeaderText;
328
329/// Marker component for header node
330#[derive(Debug, Clone, Component, Default, Reflect)]
331pub struct HeaderNode;
332
333fn update_active_cameras(
334 state: Res<State<CameraActive>>,
335 camera_2d: Single<(Entity, &mut Camera), With<Camera2d>>,
336 camera_3d: Single<(Entity, &mut Camera), (With<Camera3d>, Without<Camera2d>)>,
337 mut text: Query<&mut TargetCamera, With<HeaderNode>>,
338) {
339 let (entity_2d, mut cam_2d) = camera_2d.into_inner();
340 let (entity_3d, mut cam_3d) = camera_3d.into_inner();
341 let is_camera_2d_active = matches!(*state.get(), CameraActive::Dim2);
342
343 cam_2d.is_active = is_camera_2d_active;
344 cam_3d.is_active = !is_camera_2d_active;
345
346 let active_camera = if is_camera_2d_active {
347 entity_2d
348 } else {
349 entity_3d
350 };
351
352 text.iter_mut().for_each(|mut target_camera| {
353 *target_camera = TargetCamera(active_camera);
354 });
355}
356
357fn switch_cameras(current: Res<State<CameraActive>>, mut next: ResMut<NextState<CameraActive>>) {
358 let next_state = match current.get() {
359 CameraActive::Dim2 => CameraActive::Dim3,
360 CameraActive::Dim3 => CameraActive::Dim2,
361 };
362 next.set(next_state);
363}
364
365fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
366 let active_camera = cameras
367 .iter()
368 .find_map(|(entity, camera)| camera.is_active.then_some(entity))
369 .expect("run condition ensures existence");
370 commands
371 .spawn((
372 HeaderNode,
373 Node {
374 justify_self: JustifySelf::Center,
375 top: Val::Px(5.0),
376 ..Default::default()
377 },
378 TargetCamera(active_camera),
379 ))
380 .with_children(|p| {
381 p.spawn((
382 Text::default(),
383 HeaderText,
384 TextLayout::new_with_justify(JustifyText::Center),
385 ))
386 .with_children(|p| {
387 p.spawn(TextSpan::new("Primitive: "));
388 p.spawn(TextSpan(format!(
389 "{text}",
390 text = PrimitiveSelected::default()
391 )));
392 p.spawn(TextSpan::new("\n\n"));
393 p.spawn(TextSpan::new(
394 "Press 'C' to switch between 2D and 3D mode\n\
395 Press 'Up' or 'Down' to switch to the next/previous primitive",
396 ));
397 p.spawn(TextSpan::new("\n\n"));
398 p.spawn(TextSpan::new(
399 "(If nothing is displayed, there's no rendering support yet)",
400 ));
401 });
402 });
403}
404
405fn update_text(
406 primitive_state: Res<State<PrimitiveSelected>>,
407 header: Query<Entity, With<HeaderText>>,
408 mut writer: TextUiWriter,
409) {
410 let new_text = format!("{text}", text = primitive_state.get());
411 header.iter().for_each(|header_text| {
412 if let Some(mut text) = writer.get_text(header_text, 2) {
413 (*text).clone_from(&new_text);
414 };
415 });
416}
417
418fn switch_to_next_primitive(
419 current: Res<State<PrimitiveSelected>>,
420 mut next: ResMut<NextState<PrimitiveSelected>>,
421) {
422 let next_state = current.get().next();
423 next.set(next_state);
424}
425
426fn switch_to_previous_primitive(
427 current: Res<State<PrimitiveSelected>>,
428 mut next: ResMut<NextState<PrimitiveSelected>>,
429) {
430 let next_state = current.get().previous();
431 next.set(next_state);
432}
433
434fn in_mode(active: CameraActive) -> impl Fn(Res<State<CameraActive>>) -> bool {
435 move |state| *state.get() == active
436}
437
438fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
439 const POSITION: Vec2 = Vec2::new(-LEFT_RIGHT_OFFSET_2D, 0.0);
440 let angle = time.elapsed_secs();
441 let isometry = Isometry2d::new(POSITION, Rot2::radians(angle));
442 let color = Color::WHITE;
443
444 match state.get() {
445 PrimitiveSelected::RectangleAndCuboid => {
446 gizmos.primitive_2d(&RECTANGLE, isometry, color);
447 }
448 PrimitiveSelected::CircleAndSphere => {
449 gizmos.primitive_2d(&CIRCLE, isometry, color);
450 }
451 PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, isometry, color)),
452 PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, isometry, color),
453 PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, isometry, color),
454 PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, isometry, color)),
455 PrimitiveSelected::Segment => {
456 drop(gizmos.primitive_2d(&SEGMENT_2D, isometry, color));
457 }
458 PrimitiveSelected::Polyline => gizmos.primitive_2d(&POLYLINE_2D, isometry, color),
459 PrimitiveSelected::Polygon => gizmos.primitive_2d(&POLYGON_2D, isometry, color),
460 PrimitiveSelected::RegularPolygon => {
461 gizmos.primitive_2d(®ULAR_POLYGON, isometry, color);
462 }
463 PrimitiveSelected::Capsule => gizmos.primitive_2d(&CAPSULE_2D, isometry, color),
464 PrimitiveSelected::Cylinder => {}
465 PrimitiveSelected::Cone => {}
466 PrimitiveSelected::ConicalFrustum => {}
467 PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, isometry, color)),
468 PrimitiveSelected::Tetrahedron => {}
469 PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, isometry, color),
470 PrimitiveSelected::CircularSector => {
471 gizmos.primitive_2d(&CIRCULAR_SECTOR, isometry, color);
472 }
473 PrimitiveSelected::CircularSegment => {
474 gizmos.primitive_2d(&CIRCULAR_SEGMENT, isometry, color);
475 }
476 }
477}
478
479/// Marker for primitive meshes to record in which state they should be visible in
480#[derive(Debug, Clone, Component, Default, Reflect)]
481pub struct PrimitiveData {
482 camera_mode: CameraActive,
483 primitive_state: PrimitiveSelected,
484}
485
486/// Marker for meshes of 2D primitives
487#[derive(Debug, Clone, Component, Default)]
488pub struct MeshDim2;
489
490/// Marker for meshes of 3D primitives
491#[derive(Debug, Clone, Component, Default)]
492pub struct MeshDim3;
493
494fn spawn_primitive_2d(
495 mut commands: Commands,
496 mut materials: ResMut<Assets<ColorMaterial>>,
497 mut meshes: ResMut<Assets<Mesh>>,
498) {
499 const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_2D, 0.0, 0.0);
500 let material: Handle<ColorMaterial> = materials.add(Color::WHITE);
501 let camera_mode = CameraActive::Dim2;
502 [
503 Some(RECTANGLE.mesh().build()),
504 Some(CIRCLE.mesh().build()),
505 Some(ELLIPSE.mesh().build()),
506 Some(TRIANGLE_2D.mesh().build()),
507 None, // plane
508 None, // line
509 None, // segment
510 None, // polyline
511 None, // polygon
512 Some(REGULAR_POLYGON.mesh().build()),
513 Some(CAPSULE_2D.mesh().build()),
514 None, // cylinder
515 None, // cone
516 None, // conical frustum
517 Some(ANNULUS.mesh().build()),
518 None, // tetrahedron
519 ]
520 .into_iter()
521 .zip(PrimitiveSelected::ALL)
522 .for_each(|(maybe_mesh, state)| {
523 if let Some(mesh) = maybe_mesh {
524 commands.spawn((
525 MeshDim2,
526 PrimitiveData {
527 camera_mode,
528 primitive_state: state,
529 },
530 Mesh2d(meshes.add(mesh)),
531 MeshMaterial2d(material.clone()),
532 Transform::from_translation(POSITION),
533 ));
534 }
535 });
536}
537
538fn spawn_primitive_3d(
539 mut commands: Commands,
540 mut materials: ResMut<Assets<StandardMaterial>>,
541 mut meshes: ResMut<Assets<Mesh>>,
542) {
543 const POSITION: Vec3 = Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
544 let material: Handle<StandardMaterial> = materials.add(Color::WHITE);
545 let camera_mode = CameraActive::Dim3;
546 [
547 Some(CUBOID.mesh().build()),
548 Some(SPHERE.mesh().build()),
549 None, // ellipse
550 Some(TRIANGLE_3D.mesh().build()),
551 Some(PLANE_3D.mesh().build()),
552 None, // line
553 None, // segment
554 None, // polyline
555 None, // polygon
556 None, // regular polygon
557 Some(CAPSULE_3D.mesh().build()),
558 Some(CYLINDER.mesh().build()),
559 None, // cone
560 None, // conical frustum
561 Some(TORUS.mesh().build()),
562 Some(TETRAHEDRON.mesh().build()),
563 ]
564 .into_iter()
565 .zip(PrimitiveSelected::ALL)
566 .for_each(|(maybe_mesh, state)| {
567 if let Some(mesh) = maybe_mesh {
568 commands.spawn((
569 MeshDim3,
570 PrimitiveData {
571 camera_mode,
572 primitive_state: state,
573 },
574 Mesh3d(meshes.add(mesh)),
575 MeshMaterial3d(material.clone()),
576 Transform::from_translation(POSITION),
577 ));
578 }
579 });
580}
581
582fn update_primitive_meshes(
583 camera_state: Res<State<CameraActive>>,
584 primitive_state: Res<State<PrimitiveSelected>>,
585 mut primitives: Query<(&mut Visibility, &PrimitiveData)>,
586) {
587 primitives.iter_mut().for_each(|(mut vis, primitive)| {
588 let visible = primitive.camera_mode == *camera_state.get()
589 && primitive.primitive_state == *primitive_state.get();
590 *vis = if visible {
591 Visibility::Inherited
592 } else {
593 Visibility::Hidden
594 };
595 });
596}
597
598fn rotate_primitive_2d_meshes(
599 mut primitives_2d: Query<
600 (&mut Transform, &ViewVisibility),
601 (With<PrimitiveData>, With<MeshDim2>),
602 >,
603 time: Res<Time>,
604) {
605 let rotation_2d = Quat::from_mat3(&Mat3::from_angle(time.elapsed_secs()));
606 primitives_2d
607 .iter_mut()
608 .filter(|(_, vis)| vis.get())
609 .for_each(|(mut transform, _)| {
610 transform.rotation = rotation_2d;
611 });
612}
613
614fn rotate_primitive_3d_meshes(
615 mut primitives_3d: Query<
616 (&mut Transform, &ViewVisibility),
617 (With<PrimitiveData>, With<MeshDim3>),
618 >,
619 time: Res<Time>,
620) {
621 let rotation_3d = Quat::from_rotation_arc(
622 Vec3::Z,
623 Vec3::new(
624 ops::sin(time.elapsed_secs()),
625 ops::cos(time.elapsed_secs()),
626 ops::sin(time.elapsed_secs()) * 0.5,
627 )
628 .try_normalize()
629 .unwrap_or(Vec3::Z),
630 );
631 primitives_3d
632 .iter_mut()
633 .filter(|(_, vis)| vis.get())
634 .for_each(|(mut transform, _)| {
635 transform.rotation = rotation_3d;
636 });
637}
638
639fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
640 const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
641 let rotation = Quat::from_rotation_arc(
642 Vec3::Z,
643 Vec3::new(
644 ops::sin(time.elapsed_secs()),
645 ops::cos(time.elapsed_secs()),
646 ops::sin(time.elapsed_secs()) * 0.5,
647 )
648 .try_normalize()
649 .unwrap_or(Vec3::Z),
650 );
651 let isometry = Isometry3d::new(POSITION, rotation);
652 let color = Color::WHITE;
653 let resolution = 10;
654
655 match state.get() {
656 PrimitiveSelected::RectangleAndCuboid => {
657 gizmos.primitive_3d(&CUBOID, isometry, color);
658 }
659 PrimitiveSelected::CircleAndSphere => drop(
660 gizmos
661 .primitive_3d(&SPHERE, isometry, color)
662 .resolution(resolution),
663 ),
664 PrimitiveSelected::Ellipse => {}
665 PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, isometry, color),
666 PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, isometry, color)),
667 PrimitiveSelected::Line => gizmos.primitive_3d(&LINE3D, isometry, color),
668 PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, isometry, color),
669 PrimitiveSelected::Polyline => gizmos.primitive_3d(&POLYLINE_3D, isometry, color),
670 PrimitiveSelected::Polygon => {}
671 PrimitiveSelected::RegularPolygon => {}
672 PrimitiveSelected::Capsule => drop(
673 gizmos
674 .primitive_3d(&CAPSULE_3D, isometry, color)
675 .resolution(resolution),
676 ),
677 PrimitiveSelected::Cylinder => drop(
678 gizmos
679 .primitive_3d(&CYLINDER, isometry, color)
680 .resolution(resolution),
681 ),
682 PrimitiveSelected::Cone => drop(
683 gizmos
684 .primitive_3d(&CONE, isometry, color)
685 .resolution(resolution),
686 ),
687 PrimitiveSelected::ConicalFrustum => {
688 gizmos.primitive_3d(&CONICAL_FRUSTUM, isometry, color);
689 }
690
691 PrimitiveSelected::Torus => drop(
692 gizmos
693 .primitive_3d(&TORUS, isometry, color)
694 .minor_resolution(resolution)
695 .major_resolution(resolution),
696 ),
697 PrimitiveSelected::Tetrahedron => {
698 gizmos.primitive_3d(&TETRAHEDRON, isometry, color);
699 }
700
701 PrimitiveSelected::Arc => {}
702 PrimitiveSelected::CircularSector => {}
703 PrimitiveSelected::CircularSegment => {}
704 }
705}
66fn move_text(
67 mut commands: Commands,
68 mut texts: Query<(Entity, &mut Transform), With<Text2d>>,
69 time: Res<Time>,
70) {
71 for (entity, mut position) in &mut texts {
72 position.translation -= Vec3::new(0.0, 100.0 * time.delta_secs(), 0.0);
73 if position.translation.y < -300.0 {
74 commands.entity(entity).despawn();
75 }
76 }
77}
20fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
21 // Create a camera
22 commands.spawn((
23 Camera3d::default(),
24 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y),
25 ));
26
27 // Spawn the first scene in `models/SimpleSkin/SimpleSkin.gltf`
28 commands.spawn(SceneRoot(asset_server.load(
29 GltfAssetLabel::Scene(0).from_asset("models/SimpleSkin/SimpleSkin.gltf"),
30 )));
31}
121fn setup_env(mut commands: Commands) {
122 // Used to center camera on spawned cubes
123 let offset = if NUM_CUBES % 2 == 0 {
124 (NUM_CUBES / 2) as f32 - 0.5
125 } else {
126 (NUM_CUBES / 2) as f32
127 };
128
129 // lights
130 commands.spawn((PointLight::default(), Transform::from_xyz(4.0, 12.0, 15.0)));
131
132 // camera
133 commands.spawn((
134 Camera3d::default(),
135 Transform::from_xyz(offset, offset, 15.0)
136 .looking_at(Vec3::new(offset, offset, 0.0), Vec3::Y),
137 ));
138}
- examples/3d/query_gltf_primitives.rs
- examples/shader/array_texture.rs
- examples/shader/fallback_image.rs
- examples/3d/parallax_mapping.rs
- examples/shader/texture_binding_array.rs
- examples/camera/2d_top_down_camera.rs
- examples/2d/sprite_slice.rs
- examples/asset/multi_asset_sync.rs
- examples/animation/animated_fox.rs
- examples/stress_tests/bevymark.rs
- examples/3d/mesh_ray_cast.rs
- examples/3d/color_grading.rs
- examples/3d/atmospheric_fog.rs
- examples/3d/post_processing.rs
- examples/games/loading_screen.rs
- examples/shader/custom_post_processing.rs
- examples/animation/animation_graph.rs
- examples/testbed/2d.rs
- examples/3d/tonemapping.rs
- examples/animation/animation_masks.rs
- examples/3d/animated_material.rs
- examples/3d/load_gltf.rs
- examples/3d/lines.rs
- examples/3d/update_gltf_scene.rs
- examples/shader/custom_shader_instancing.rs
- examples/2d/mesh2d_vertex_color_texture.rs
- examples/3d/order_independent_transparency.rs
- examples/audio/spatial_audio_2d.rs
- examples/games/contributors.rs
- examples/2d/bloom_2d.rs
- examples/3d/motion_blur.rs
- examples/gizmos/axes.rs
- examples/animation/eased_motion.rs
- examples/3d/fog.rs
- examples/2d/sprite_animation.rs
- examples/testbed/3d.rs
- examples/3d/shadow_caster_receiver.rs
- examples/time/virtual_time.rs
- examples/stress_tests/many_lights.rs
- examples/3d/anti_aliasing.rs
- examples/animation/easing_functions.rs
- examples/3d/scrolling_fog.rs
- examples/2d/mesh2d_arcs.rs
- examples/ecs/iter_combinations.rs
- examples/games/alien_cake_addict.rs
- examples/3d/3d_shapes.rs
- examples/3d/meshlet.rs
- examples/gizmos/3d_gizmos.rs
- examples/3d/render_to_texture.rs
- examples/3d/spotlight.rs
- examples/2d/text2d.rs
- examples/shader/shader_prepass.rs
- examples/picking/mesh_picking.rs
- examples/stress_tests/many_foxes.rs
- examples/3d/split_screen.rs
- examples/3d/shadow_biases.rs
- examples/games/desk_toy.rs
- examples/2d/texture_atlas.rs
- examples/3d/deferred_rendering.rs
- examples/animation/custom_skinned_mesh.rs
- examples/stress_tests/many_cubes.rs
- examples/animation/animated_transform.rs
- examples/3d/lighting.rs
- examples/3d/transmission.rs
Sourcepub const fn splat(v: f32) -> Vec3
pub const fn splat(v: f32) -> Vec3
Creates a vector with all elements set to v
.
Examples found in repository?
267fn spawn_sphere(commands: &mut Commands, assets: &ExampleAssets) {
268 commands
269 .spawn((
270 Mesh3d(assets.main_sphere.clone()),
271 MeshMaterial3d(assets.main_sphere_material.clone()),
272 Transform::from_xyz(0.0, SPHERE_SCALE, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
273 ))
274 .insert(MainObject);
275}
276
277fn spawn_voxel_cube_parent(commands: &mut Commands) {
278 commands.spawn((Visibility::Hidden, Transform::default(), VoxelCubeParent));
279}
280
281fn spawn_fox(commands: &mut Commands, assets: &ExampleAssets) {
282 commands.spawn((
283 SceneRoot(assets.fox.clone()),
284 Visibility::Hidden,
285 Transform::from_scale(Vec3::splat(FOX_SCALE)),
286 MainObject,
287 ));
288}
289
290fn spawn_text(commands: &mut Commands, app_status: &AppStatus) {
291 commands.spawn((
292 app_status.create_text(),
293 Node {
294 position_type: PositionType::Absolute,
295 bottom: Val::Px(12.0),
296 left: Val::Px(12.0),
297 ..default()
298 },
299 ));
300}
301
302// A system that updates the help text.
303fn update_text(mut text_query: Query<&mut Text>, app_status: Res<AppStatus>) {
304 for mut text in text_query.iter_mut() {
305 *text = app_status.create_text();
306 }
307}
308
309impl AppStatus {
310 // Constructs the help text at the bottom of the screen based on the
311 // application status.
312 fn create_text(&self) -> Text {
313 let irradiance_volume_help_text = if self.irradiance_volume_present {
314 DISABLE_IRRADIANCE_VOLUME_HELP_TEXT
315 } else {
316 ENABLE_IRRADIANCE_VOLUME_HELP_TEXT
317 };
318
319 let voxels_help_text = if self.voxels_visible {
320 HIDE_VOXELS_HELP_TEXT
321 } else {
322 SHOW_VOXELS_HELP_TEXT
323 };
324
325 let rotation_help_text = if self.rotating {
326 STOP_ROTATION_HELP_TEXT
327 } else {
328 START_ROTATION_HELP_TEXT
329 };
330
331 let switch_mesh_help_text = match self.model {
332 ExampleModel::Sphere => SWITCH_TO_FOX_HELP_TEXT,
333 ExampleModel::Fox => SWITCH_TO_SPHERE_HELP_TEXT,
334 };
335
336 format!(
337 "{CLICK_TO_MOVE_HELP_TEXT}\n\
338 {voxels_help_text}\n\
339 {irradiance_volume_help_text}\n\
340 {rotation_help_text}\n\
341 {switch_mesh_help_text}"
342 )
343 .into()
344 }
345}
346
347// Rotates the camera a bit every frame.
348fn rotate_camera(
349 mut camera_query: Query<&mut Transform, With<Camera3d>>,
350 time: Res<Time>,
351 app_status: Res<AppStatus>,
352) {
353 if !app_status.rotating {
354 return;
355 }
356
357 for mut transform in camera_query.iter_mut() {
358 transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
359 .rotate(transform.translation.xz())
360 .extend(transform.translation.y)
361 .xzy();
362 transform.look_at(Vec3::ZERO, Vec3::Y);
363 }
364}
365
366// Toggles between the unskinned sphere model and the skinned fox model if the
367// user requests it.
368fn change_main_object(
369 keyboard: Res<ButtonInput<KeyCode>>,
370 mut app_status: ResMut<AppStatus>,
371 mut sphere_query: Query<&mut Visibility, (With<MainObject>, With<Mesh3d>, Without<SceneRoot>)>,
372 mut fox_query: Query<&mut Visibility, (With<MainObject>, With<SceneRoot>)>,
373) {
374 if !keyboard.just_pressed(KeyCode::Tab) {
375 return;
376 }
377 let Some(mut sphere_visibility) = sphere_query.iter_mut().next() else {
378 return;
379 };
380 let Some(mut fox_visibility) = fox_query.iter_mut().next() else {
381 return;
382 };
383
384 match app_status.model {
385 ExampleModel::Sphere => {
386 *sphere_visibility = Visibility::Hidden;
387 *fox_visibility = Visibility::Visible;
388 app_status.model = ExampleModel::Fox;
389 }
390 ExampleModel::Fox => {
391 *sphere_visibility = Visibility::Visible;
392 *fox_visibility = Visibility::Hidden;
393 app_status.model = ExampleModel::Sphere;
394 }
395 }
396}
397
398impl Default for AppStatus {
399 fn default() -> Self {
400 Self {
401 irradiance_volume_present: true,
402 rotating: true,
403 model: ExampleModel::Sphere,
404 voxels_visible: false,
405 }
406 }
407}
408
409// Turns on and off the irradiance volume as requested by the user.
410fn toggle_irradiance_volumes(
411 mut commands: Commands,
412 keyboard: Res<ButtonInput<KeyCode>>,
413 light_probe_query: Query<Entity, With<LightProbe>>,
414 mut app_status: ResMut<AppStatus>,
415 assets: Res<ExampleAssets>,
416 mut ambient_light: ResMut<AmbientLight>,
417) {
418 if !keyboard.just_pressed(KeyCode::Space) {
419 return;
420 };
421
422 let Some(light_probe) = light_probe_query.iter().next() else {
423 return;
424 };
425
426 if app_status.irradiance_volume_present {
427 commands.entity(light_probe).remove::<IrradianceVolume>();
428 ambient_light.brightness = AMBIENT_LIGHT_BRIGHTNESS * IRRADIANCE_VOLUME_INTENSITY;
429 app_status.irradiance_volume_present = false;
430 } else {
431 commands.entity(light_probe).insert(IrradianceVolume {
432 voxels: assets.irradiance_volume.clone(),
433 intensity: IRRADIANCE_VOLUME_INTENSITY,
434 });
435 ambient_light.brightness = 0.0;
436 app_status.irradiance_volume_present = true;
437 }
438}
439
440fn toggle_rotation(keyboard: Res<ButtonInput<KeyCode>>, mut app_status: ResMut<AppStatus>) {
441 if keyboard.just_pressed(KeyCode::Enter) {
442 app_status.rotating = !app_status.rotating;
443 }
444}
445
446// Handles clicks on the plane that reposition the object.
447fn handle_mouse_clicks(
448 buttons: Res<ButtonInput<MouseButton>>,
449 windows: Query<&Window, With<PrimaryWindow>>,
450 cameras: Query<(&Camera, &GlobalTransform)>,
451 mut main_objects: Query<&mut Transform, With<MainObject>>,
452) {
453 if !buttons.pressed(MouseButton::Left) {
454 return;
455 }
456 let Some(mouse_position) = windows.iter().next().and_then(Window::cursor_position) else {
457 return;
458 };
459 let Some((camera, camera_transform)) = cameras.iter().next() else {
460 return;
461 };
462
463 // Figure out where the user clicked on the plane.
464 let Ok(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
465 return;
466 };
467 let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else {
468 return;
469 };
470 let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;
471
472 // Move all the main objeccts.
473 for mut transform in main_objects.iter_mut() {
474 transform.translation = vec3(
475 plane_intersection.x,
476 transform.translation.y,
477 plane_intersection.z,
478 );
479 }
480}
481
482impl FromWorld for ExampleAssets {
483 fn from_world(world: &mut World) -> Self {
484 let fox_animation =
485 world.load_asset(GltfAssetLabel::Animation(1).from_asset("models/animated/Fox.glb"));
486 let (fox_animation_graph, fox_animation_node) =
487 AnimationGraph::from_clip(fox_animation.clone());
488
489 ExampleAssets {
490 main_sphere: world.add_asset(Sphere::default().mesh().uv(32, 18)),
491 fox: world.load_asset(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")),
492 main_sphere_material: world.add_asset(Color::from(SILVER)),
493 main_scene: world.load_asset(
494 GltfAssetLabel::Scene(0)
495 .from_asset("models/IrradianceVolumeExample/IrradianceVolumeExample.glb"),
496 ),
497 irradiance_volume: world.load_asset("irradiance_volumes/Example.vxgi.ktx2"),
498 fox_animation_graph: world.add_asset(fox_animation_graph),
499 fox_animation_node,
500 voxel_cube: world.add_asset(Cuboid::default()),
501 // Just use a specular map for the skybox since it's not too blurry.
502 // In reality you wouldn't do this--you'd use a real skybox texture--but
503 // reusing the textures like this saves space in the Bevy repository.
504 skybox: world.load_asset("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
505 }
506 }
507}
508
509// Plays the animation on the fox.
510fn play_animations(
511 mut commands: Commands,
512 assets: Res<ExampleAssets>,
513 mut players: Query<(Entity, &mut AnimationPlayer), Without<AnimationGraphHandle>>,
514) {
515 for (entity, mut player) in players.iter_mut() {
516 commands
517 .entity(entity)
518 .insert(AnimationGraphHandle(assets.fox_animation_graph.clone()));
519 player.play(assets.fox_animation_node).repeat();
520 }
521}
522
523fn create_cubes(
524 image_assets: Res<Assets<Image>>,
525 mut commands: Commands,
526 irradiance_volumes: Query<(&IrradianceVolume, &GlobalTransform)>,
527 voxel_cube_parents: Query<Entity, With<VoxelCubeParent>>,
528 voxel_cubes: Query<Entity, With<VoxelCube>>,
529 example_assets: Res<ExampleAssets>,
530 mut voxel_visualization_material_assets: ResMut<Assets<VoxelVisualizationMaterial>>,
531) {
532 // If voxel cubes have already been spawned, don't do anything.
533 if !voxel_cubes.is_empty() {
534 return;
535 }
536
537 let Some(voxel_cube_parent) = voxel_cube_parents.iter().next() else {
538 return;
539 };
540
541 for (irradiance_volume, global_transform) in irradiance_volumes.iter() {
542 let Some(image) = image_assets.get(&irradiance_volume.voxels) else {
543 continue;
544 };
545
546 let resolution = image.texture_descriptor.size;
547
548 let voxel_cube_material = voxel_visualization_material_assets.add(ExtendedMaterial {
549 base: StandardMaterial::from(Color::from(RED)),
550 extension: VoxelVisualizationExtension {
551 irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo {
552 world_from_voxel: VOXEL_FROM_WORLD.inverse(),
553 voxel_from_world: VOXEL_FROM_WORLD,
554 resolution: uvec3(
555 resolution.width,
556 resolution.height,
557 resolution.depth_or_array_layers,
558 ),
559 intensity: IRRADIANCE_VOLUME_INTENSITY,
560 },
561 },
562 });
563
564 let scale = vec3(
565 1.0 / resolution.width as f32,
566 1.0 / resolution.height as f32,
567 1.0 / resolution.depth_or_array_layers as f32,
568 );
569
570 // Spawn a cube for each voxel.
571 for z in 0..resolution.depth_or_array_layers {
572 for y in 0..resolution.height {
573 for x in 0..resolution.width {
574 let uvw = (uvec3(x, y, z).as_vec3() + 0.5) * scale - 0.5;
575 let pos = global_transform.transform_point(uvw);
576 let voxel_cube = commands
577 .spawn((
578 Mesh3d(example_assets.voxel_cube.clone()),
579 MeshMaterial3d(voxel_cube_material.clone()),
580 Transform::from_scale(Vec3::splat(VOXEL_CUBE_SCALE))
581 .with_translation(pos),
582 ))
583 .insert(VoxelCube)
584 .insert(NotShadowCaster)
585 .id();
586
587 commands.entity(voxel_cube_parent).add_child(voxel_cube);
588 }
589 }
590 }
591 }
592}
More examples
12fn setup(
13 mut commands: Commands,
14 mut meshes: ResMut<Assets<Mesh>>,
15 mut materials: ResMut<Assets<ColorMaterial>>,
16) {
17 commands.spawn(Camera2d);
18 commands.spawn((
19 Mesh2d(meshes.add(Rectangle::default())),
20 MeshMaterial2d(materials.add(Color::from(PURPLE))),
21 Transform::default().with_scale(Vec3::splat(128.)),
22 ));
23}
162fn spawn_flight_helmet(commands: &mut Commands, asset_server: &AssetServer) {
163 commands.spawn((
164 SceneRoot(
165 asset_server
166 .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")),
167 ),
168 Transform::from_scale(Vec3::splat(2.5)),
169 FlightHelmetModel,
170 Visibility::Hidden,
171 ));
172}
173
174// Spawns the water plane.
175fn spawn_water(
176 commands: &mut Commands,
177 asset_server: &AssetServer,
178 meshes: &mut Assets<Mesh>,
179 water_materials: &mut Assets<ExtendedMaterial<StandardMaterial, Water>>,
180) {
181 commands.spawn((
182 Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0)))),
183 MeshMaterial3d(water_materials.add(ExtendedMaterial {
184 base: StandardMaterial {
185 base_color: BLACK.into(),
186 perceptual_roughness: 0.0,
187 ..default()
188 },
189 extension: Water {
190 normals: asset_server.load_with_settings::<Image, ImageLoaderSettings>(
191 "textures/water_normals.png",
192 |settings| {
193 settings.is_srgb = false;
194 settings.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor {
195 address_mode_u: ImageAddressMode::Repeat,
196 address_mode_v: ImageAddressMode::Repeat,
197 mag_filter: ImageFilterMode::Linear,
198 min_filter: ImageFilterMode::Linear,
199 ..default()
200 });
201 },
202 ),
203 // These water settings are just random values to create some
204 // variety.
205 settings: WaterSettings {
206 octave_vectors: [
207 vec4(0.080, 0.059, 0.073, -0.062),
208 vec4(0.153, 0.138, -0.149, -0.195),
209 ],
210 octave_scales: vec4(1.0, 2.1, 7.9, 14.9) * 5.0,
211 octave_strengths: vec4(0.16, 0.18, 0.093, 0.044),
212 },
213 },
214 })),
215 Transform::from_scale(Vec3::splat(100.0)),
216 ));
217}
71fn setup_mesh(
72 mut commands: Commands,
73 mut meshes: ResMut<Assets<Mesh>>,
74 mut materials: ResMut<Assets<ColorMaterial>>,
75) {
76 commands.spawn((
77 Mesh2d(meshes.add(Capsule2d::default())),
78 MeshMaterial2d(materials.add(Color::BLACK)),
79 Transform::from_xyz(40., 0., 2.).with_scale(Vec3::splat(32.)),
80 Rotate,
81 PIXEL_PERFECT_LAYERS,
82 ));
83}
132fn spawn_player(mut commands: Commands, asset_server: Res<AssetServer>) {
133 commands.spawn(Camera2d);
134 commands.spawn((
135 Name::new("Player"),
136 Sprite::from_image(asset_server.load("branding/icon.png")),
137 Transform::from_scale(Vec3::splat(0.3)),
138 AccumulatedInput::default(),
139 Velocity::default(),
140 PhysicalTranslation::default(),
141 PreviousPhysicalTranslation::default(),
142 ));
143}
- examples/math/sampling_primitives.rs
- examples/3d/reflection_probes.rs
- examples/shader/shader_material_2d.rs
- examples/animation/animated_fox.rs
- examples/ecs/parallel_query.rs
- examples/3d/rotate_environment_map.rs
- examples/stress_tests/bevymark.rs
- examples/3d/clearcoat.rs
- examples/2d/sprite_sheet.rs
- examples/animation/animation_graph.rs
- examples/shader/compute_shader_game_of_life.rs
- examples/animation/animation_masks.rs
- examples/movement/smooth_follow.rs
- examples/shader/automatic_instancing.rs
- examples/shader/storage_buffer.rs
- examples/3d/atmospheric_fog.rs
- examples/ecs/hierarchy.rs
- examples/2d/mesh2d_vertex_color_texture.rs
- examples/transforms/transform.rs
- examples/stress_tests/many_sprites.rs
- examples/3d/spherical_area_lights.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/3d/motion_blur.rs
- examples/camera/projection_zoom.rs
- examples/3d/fog.rs
- examples/2d/sprite_animation.rs
- examples/3d/volumetric_fog.rs
- examples/stress_tests/many_lights.rs
- examples/picking/sprite_picking.rs
- examples/3d/scrolling_fog.rs
- examples/ecs/iter_combinations.rs
- examples/3d/meshlet.rs
- examples/gizmos/3d_gizmos.rs
- examples/stress_tests/many_foxes.rs
- examples/2d/texture_atlas.rs
- examples/3d/deferred_rendering.rs
- examples/stress_tests/many_cubes.rs
- examples/animation/animated_transform.rs
- examples/3d/transmission.rs
Sourcepub fn map<F>(self, f: F) -> Vec3
pub fn map<F>(self, f: F) -> Vec3
Returns a vector containing each element of self
modified by a mapping function f
.
Sourcepub fn select(mask: BVec3, if_true: Vec3, if_false: Vec3) -> Vec3
pub fn select(mask: BVec3, if_true: Vec3, if_false: Vec3) -> Vec3
Creates a vector from the elements in if_true
and if_false
, selecting which to use
for each element of self
.
A true element in the mask uses the corresponding element from if_true
, and false
uses the element from if_false
.
Sourcepub const fn from_array(a: [f32; 3]) -> Vec3
pub const fn from_array(a: [f32; 3]) -> Vec3
Creates a new vector from an array.
Sourcepub const fn from_slice(slice: &[f32]) -> Vec3
pub const fn from_slice(slice: &[f32]) -> Vec3
Creates a vector from the first 3 values in slice
.
§Panics
Panics if slice
is less than 3 elements long.
Sourcepub fn write_to_slice(self, slice: &mut [f32])
pub fn write_to_slice(self, slice: &mut [f32])
Writes the elements of self
to the first 3 elements in slice
.
§Panics
Panics if slice
is less than 3 elements long.
Sourcepub fn truncate(self) -> Vec2
pub fn truncate(self) -> Vec2
Creates a 2D vector from the x
and y
elements of self
, discarding z
.
Truncation may also be performed by using self.xy()
.
Examples found in repository?
172fn handle_click(
173 mouse_button_input: Res<ButtonInput<MouseButton>>,
174 camera: Single<(&Camera, &GlobalTransform)>,
175 windows: Single<&Window>,
176 mut commands: Commands,
177) {
178 let (camera, camera_transform) = *camera;
179 if let Some(pos) = windows
180 .cursor_position()
181 .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
182 .map(|ray| ray.origin.truncate())
183 {
184 if mouse_button_input.just_pressed(MouseButton::Left) {
185 commands.trigger(ExplodeMines { pos, radius: 1.0 });
186 }
187 }
188}
More examples
106fn draw_bounds<Shape: Bounded2d + Send + Sync + 'static>(
107 q: Query<(&DrawBounds<Shape>, &GlobalTransform)>,
108 mut gizmos: Gizmos,
109) {
110 for (shape, transform) in &q {
111 let (_, rotation, translation) = transform.to_scale_rotation_translation();
112 let translation = translation.truncate();
113 let rotation = rotation.to_euler(EulerRot::XYZ).2;
114 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
115
116 let aabb = shape.0.aabb_2d(isometry);
117 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2.0, RED);
118
119 let bounding_circle = shape.0.bounding_circle(isometry);
120 gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE);
121 }
122}
221fn update_cursor_hit_test(
222 cursor_world_pos: Res<CursorWorldPos>,
223 mut primary_window: Single<&mut Window, With<PrimaryWindow>>,
224 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
225) {
226 // If the window has decorations (e.g. a border) then it should be clickable
227 if primary_window.decorations {
228 primary_window.cursor_options.hit_test = true;
229 return;
230 }
231
232 // If the cursor is not within the window we don't need to update whether the window is clickable or not
233 let Some(cursor_world_pos) = cursor_world_pos.0 else {
234 return;
235 };
236
237 // If the cursor is within the radius of the Bevy logo make the window clickable otherwise the window is not clickable
238 primary_window.cursor_options.hit_test = bevy_logo_transform
239 .translation
240 .truncate()
241 .distance(cursor_world_pos)
242 < BEVY_LOGO_RADIUS;
243}
244
245/// Start the drag operation and record the offset we started dragging from
246fn start_drag(
247 mut commands: Commands,
248 cursor_world_pos: Res<CursorWorldPos>,
249 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
250) {
251 // If the cursor is not within the primary window skip this system
252 let Some(cursor_world_pos) = cursor_world_pos.0 else {
253 return;
254 };
255
256 // Get the offset from the cursor to the Bevy logo sprite
257 let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;
258
259 // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
260 if drag_offset.length() < BEVY_LOGO_RADIUS {
261 commands.insert_resource(DragOperation(drag_offset));
262 }
263}
264
265/// Stop the current drag operation
266fn end_drag(mut commands: Commands) {
267 commands.remove_resource::<DragOperation>();
268}
269
270/// Drag the Bevy logo
271fn drag(
272 drag_offset: Res<DragOperation>,
273 cursor_world_pos: Res<CursorWorldPos>,
274 time: Res<Time>,
275 mut bevy_transform: Single<&mut Transform, With<BevyLogo>>,
276 mut q_pupils: Query<&mut Pupil>,
277) {
278 // If the cursor is not within the primary window skip this system
279 let Some(cursor_world_pos) = cursor_world_pos.0 else {
280 return;
281 };
282
283 // Calculate the new translation of the Bevy logo based on cursor and drag offset
284 let new_translation = cursor_world_pos + drag_offset.0;
285
286 // Calculate how fast we are dragging the Bevy logo (unit/second)
287 let drag_velocity =
288 (new_translation - bevy_transform.translation.truncate()) / time.delta_secs();
289
290 // Update the translation of Bevy logo transform to new translation
291 bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);
292
293 // Add the cursor drag velocity in the opposite direction to each pupil.
294 // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
295 // simulate inertia, otherwise they will move fixed to the parent.
296 for mut pupil in &mut q_pupils {
297 pupil.velocity -= drag_velocity;
298 }
299}
300
301/// Quit when the user right clicks the Bevy logo
302fn quit(
303 cursor_world_pos: Res<CursorWorldPos>,
304 mut app_exit: EventWriter<AppExit>,
305 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
306) {
307 // If the cursor is not within the primary window skip this system
308 let Some(cursor_world_pos) = cursor_world_pos.0 else {
309 return;
310 };
311
312 // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
313 if bevy_logo_transform
314 .translation
315 .truncate()
316 .distance(cursor_world_pos)
317 < BEVY_LOGO_RADIUS
318 {
319 app_exit.send(AppExit::Success);
320 }
321}
322
323/// Enable transparency for the window and make it on top
324fn toggle_transparency(
325 mut commands: Commands,
326 mut window_transparency: ResMut<WindowTransparency>,
327 mut q_instructions_text: Query<&mut Visibility, With<InstructionsText>>,
328 mut primary_window: Single<&mut Window, With<PrimaryWindow>>,
329) {
330 // Toggle the window transparency resource
331 window_transparency.0 = !window_transparency.0;
332
333 // Show or hide the instructions text
334 for mut visibility in &mut q_instructions_text {
335 *visibility = if window_transparency.0 {
336 Visibility::Hidden
337 } else {
338 Visibility::Visible
339 };
340 }
341
342 // Remove the primary window's decorations (e.g. borders), make it always on top of other desktop windows, and set the clear color to transparent
343 // only if window transparency is enabled
344 let clear_color;
345 (
346 primary_window.decorations,
347 primary_window.window_level,
348 clear_color,
349 ) = if window_transparency.0 {
350 (false, WindowLevel::AlwaysOnTop, Color::NONE)
351 } else {
352 (true, WindowLevel::Normal, WINDOW_CLEAR_COLOR)
353 };
354
355 // Set the clear color
356 commands.insert_resource(ClearColor(clear_color));
357}
358
359/// Move the pupils and bounce them around
360fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
361 for (mut pupil, mut transform) in &mut q_pupils {
362 // The wiggle radius is how much the pupil can move within the eye
363 let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
364 // Store the Z component
365 let z = transform.translation.z;
366 // Truncate the Z component to make the calculations be on [`Vec2`]
367 let mut translation = transform.translation.truncate();
368 // Decay the pupil velocity
369 pupil.velocity *= ops::powf(0.04f32, time.delta_secs());
370 // Move the pupil
371 translation += pupil.velocity * time.delta_secs();
372 // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
373 // This is not physically accurate but it's good enough for the googly eyes effect.
374 if translation.length() > wiggle_radius {
375 translation = translation.normalize() * wiggle_radius;
376 // Invert and decrease the velocity of the pupil when it bounces
377 pupil.velocity *= -0.75;
378 }
379 // Update the entity transform with the new translation after reading the Z component
380 transform.translation = translation.extend(z);
381 }
382}
344fn check_for_collisions(
345 mut commands: Commands,
346 mut score: ResMut<Score>,
347 ball_query: Single<(&mut Velocity, &Transform), With<Ball>>,
348 collider_query: Query<(Entity, &Transform, Option<&Brick>), With<Collider>>,
349 mut collision_events: EventWriter<CollisionEvent>,
350) {
351 let (mut ball_velocity, ball_transform) = ball_query.into_inner();
352
353 for (collider_entity, collider_transform, maybe_brick) in &collider_query {
354 let collision = ball_collision(
355 BoundingCircle::new(ball_transform.translation.truncate(), BALL_DIAMETER / 2.),
356 Aabb2d::new(
357 collider_transform.translation.truncate(),
358 collider_transform.scale.truncate() / 2.,
359 ),
360 );
361
362 if let Some(collision) = collision {
363 // Sends a collision event so that other systems can react to the collision
364 collision_events.send_default();
365
366 // Bricks should be despawned and increment the scoreboard on collision
367 if maybe_brick.is_some() {
368 commands.entity(collider_entity).despawn();
369 **score += 1;
370 }
371
372 // Reflect the ball's velocity when it collides
373 let mut reflect_x = false;
374 let mut reflect_y = false;
375
376 // Reflect only if the velocity is in the opposite direction of the collision
377 // This prevents the ball from getting stuck inside the bar
378 match collision {
379 Collision::Left => reflect_x = ball_velocity.x > 0.0,
380 Collision::Right => reflect_x = ball_velocity.x < 0.0,
381 Collision::Top => reflect_y = ball_velocity.y < 0.0,
382 Collision::Bottom => reflect_y = ball_velocity.y > 0.0,
383 }
384
385 // Reflect velocity on the x-axis if we hit something on the x-axis
386 if reflect_x {
387 ball_velocity.x = -ball_velocity.x;
388 }
389
390 // Reflect velocity on the y-axis if we hit something on the y-axis
391 if reflect_y {
392 ball_velocity.y = -ball_velocity.y;
393 }
394 }
395 }
396}
Sourcepub fn dot_into_vec(self, rhs: Vec3) -> Vec3
pub fn dot_into_vec(self, rhs: Vec3) -> Vec3
Returns a vector where every component is the dot product of self
and rhs
.
Sourcepub fn cross(self, rhs: Vec3) -> Vec3
pub fn cross(self, rhs: Vec3) -> Vec3
Computes the cross product of self
and rhs
.
Examples found in repository?
128fn move_pointer(
129 // `Single` ensures the system runs ONLY when exactly one matching entity exists.
130 mut player: Single<(&mut Transform, &Player)>,
131 // `Option<Single>` ensures that the system runs ONLY when zero or one matching entity exists.
132 enemy: Option<Single<&Transform, (With<Enemy>, Without<Player>)>>,
133 time: Res<Time>,
134) {
135 let (player_transform, player) = &mut *player;
136 if let Some(enemy_transform) = enemy {
137 // Enemy found, rotate and move towards it.
138 let delta = enemy_transform.translation - player_transform.translation;
139 let distance = delta.length();
140 let front = delta / distance;
141 let up = Vec3::Z;
142 let side = front.cross(up);
143 player_transform.rotation = Quat::from_mat3(&Mat3::from_cols(side, front, up));
144 let max_step = distance - player.min_follow_radius;
145 if 0.0 < max_step {
146 let velocity = (player.speed * time.delta_secs()).min(max_step);
147 player_transform.translation += front * velocity;
148 }
149 } else {
150 // No enemy found, keep searching.
151 player_transform.rotate_axis(Dir3::Z, player.rotation_speed * time.delta_secs());
152 }
153}
Sourcepub fn min(self, rhs: Vec3) -> Vec3
pub fn min(self, rhs: Vec3) -> Vec3
Returns a vector containing the minimum values for each element of self
and rhs
.
In other words this computes [self.x.min(rhs.x), self.y.min(rhs.y), ..]
.
Examples found in repository?
102fn player_movement_system(
103 time: Res<Time>,
104 keyboard_input: Res<ButtonInput<KeyCode>>,
105 query: Single<(&Player, &mut Transform)>,
106) {
107 let (ship, mut transform) = query.into_inner();
108
109 let mut rotation_factor = 0.0;
110 let mut movement_factor = 0.0;
111
112 if keyboard_input.pressed(KeyCode::ArrowLeft) {
113 rotation_factor += 1.0;
114 }
115
116 if keyboard_input.pressed(KeyCode::ArrowRight) {
117 rotation_factor -= 1.0;
118 }
119
120 if keyboard_input.pressed(KeyCode::ArrowUp) {
121 movement_factor += 1.0;
122 }
123
124 // update the ship rotation around the Z axis (perpendicular to the 2D plane of the screen)
125 transform.rotate_z(rotation_factor * ship.rotation_speed * time.delta_secs());
126
127 // get the ship's forward vector by applying the current rotation to the ships initial facing
128 // vector
129 let movement_direction = transform.rotation * Vec3::Y;
130 // get the distance the ship will move based on direction, the ship's movement speed and delta
131 // time
132 let movement_distance = movement_factor * ship.movement_speed * time.delta_secs();
133 // create the change in translation using the new movement direction and distance
134 let translation_delta = movement_direction * movement_distance;
135 // update the ship translation with our new translation delta
136 transform.translation += translation_delta;
137
138 // bound the ship within the invisible level bounds
139 let extents = Vec3::from((BOUNDS / 2.0, 0.0));
140 transform.translation = transform.translation.min(extents).max(-extents);
141}
Sourcepub fn max(self, rhs: Vec3) -> Vec3
pub fn max(self, rhs: Vec3) -> Vec3
Returns a vector containing the maximum values for each element of self
and rhs
.
In other words this computes [self.x.max(rhs.x), self.y.max(rhs.y), ..]
.
Examples found in repository?
102fn player_movement_system(
103 time: Res<Time>,
104 keyboard_input: Res<ButtonInput<KeyCode>>,
105 query: Single<(&Player, &mut Transform)>,
106) {
107 let (ship, mut transform) = query.into_inner();
108
109 let mut rotation_factor = 0.0;
110 let mut movement_factor = 0.0;
111
112 if keyboard_input.pressed(KeyCode::ArrowLeft) {
113 rotation_factor += 1.0;
114 }
115
116 if keyboard_input.pressed(KeyCode::ArrowRight) {
117 rotation_factor -= 1.0;
118 }
119
120 if keyboard_input.pressed(KeyCode::ArrowUp) {
121 movement_factor += 1.0;
122 }
123
124 // update the ship rotation around the Z axis (perpendicular to the 2D plane of the screen)
125 transform.rotate_z(rotation_factor * ship.rotation_speed * time.delta_secs());
126
127 // get the ship's forward vector by applying the current rotation to the ships initial facing
128 // vector
129 let movement_direction = transform.rotation * Vec3::Y;
130 // get the distance the ship will move based on direction, the ship's movement speed and delta
131 // time
132 let movement_distance = movement_factor * ship.movement_speed * time.delta_secs();
133 // create the change in translation using the new movement direction and distance
134 let translation_delta = movement_direction * movement_distance;
135 // update the ship translation with our new translation delta
136 transform.translation += translation_delta;
137
138 // bound the ship within the invisible level bounds
139 let extents = Vec3::from((BOUNDS / 2.0, 0.0));
140 transform.translation = transform.translation.min(extents).max(-extents);
141}
Sourcepub fn clamp(self, min: Vec3, max: Vec3) -> Vec3
pub fn clamp(self, min: Vec3, max: Vec3) -> Vec3
Component-wise clamping of values, similar to f32::clamp
.
Each element in min
must be less-or-equal to the corresponding element in max
.
§Panics
Will panic if min
is greater than max
when glam_assert
is enabled.
Sourcepub fn min_element(self) -> f32
pub fn min_element(self) -> f32
Returns the horizontal minimum of self
.
In other words this computes min(x, y, ..)
.
Examples found in repository?
65fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
66 for (mut transform, mut cube) in &mut cubes {
67 // If an entity scaled beyond the maximum of its size in any dimension
68 // the scaling vector is flipped so the scaling is gradually reverted.
69 // Additionally, to ensure the condition does not trigger again we floor the elements to
70 // their next full value, which should be max_element_size at max.
71 if transform.scale.max_element() > cube.max_element_size {
72 cube.scale_direction *= -1.0;
73 transform.scale = transform.scale.floor();
74 }
75 // If an entity scaled beyond the minimum of its size in any dimension
76 // the scaling vector is also flipped.
77 // Additionally the Values are ceiled to be min_element_size at least
78 // and the scale direction is flipped.
79 // This way the entity will change the dimension in which it is scaled any time it
80 // reaches its min_element_size.
81 if transform.scale.min_element() < cube.min_element_size {
82 cube.scale_direction *= -1.0;
83 transform.scale = transform.scale.ceil();
84 cube.scale_direction = cube.scale_direction.zxy();
85 }
86 }
87}
Sourcepub fn max_element(self) -> f32
pub fn max_element(self) -> f32
Returns the horizontal maximum of self
.
In other words this computes max(x, y, ..)
.
Examples found in repository?
65fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
66 for (mut transform, mut cube) in &mut cubes {
67 // If an entity scaled beyond the maximum of its size in any dimension
68 // the scaling vector is flipped so the scaling is gradually reverted.
69 // Additionally, to ensure the condition does not trigger again we floor the elements to
70 // their next full value, which should be max_element_size at max.
71 if transform.scale.max_element() > cube.max_element_size {
72 cube.scale_direction *= -1.0;
73 transform.scale = transform.scale.floor();
74 }
75 // If an entity scaled beyond the minimum of its size in any dimension
76 // the scaling vector is also flipped.
77 // Additionally the Values are ceiled to be min_element_size at least
78 // and the scale direction is flipped.
79 // This way the entity will change the dimension in which it is scaled any time it
80 // reaches its min_element_size.
81 if transform.scale.min_element() < cube.min_element_size {
82 cube.scale_direction *= -1.0;
83 transform.scale = transform.scale.ceil();
84 cube.scale_direction = cube.scale_direction.zxy();
85 }
86 }
87}
Sourcepub fn element_sum(self) -> f32
pub fn element_sum(self) -> f32
Returns the sum of all elements of self
.
In other words, this computes self.x + self.y + ..
.
Sourcepub fn element_product(self) -> f32
pub fn element_product(self) -> f32
Returns the product of all elements of self
.
In other words, this computes self.x * self.y * ..
.
Sourcepub fn cmpeq(self, rhs: Vec3) -> BVec3
pub fn cmpeq(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a ==
comparison for each element of
self
and rhs
.
In other words, this computes [self.x == rhs.x, self.y == rhs.y, ..]
for all
elements.
Sourcepub fn cmpne(self, rhs: Vec3) -> BVec3
pub fn cmpne(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a !=
comparison for each element of
self
and rhs
.
In other words this computes [self.x != rhs.x, self.y != rhs.y, ..]
for all
elements.
Sourcepub fn cmpge(self, rhs: Vec3) -> BVec3
pub fn cmpge(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a >=
comparison for each element of
self
and rhs
.
In other words this computes [self.x >= rhs.x, self.y >= rhs.y, ..]
for all
elements.
Sourcepub fn cmpgt(self, rhs: Vec3) -> BVec3
pub fn cmpgt(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a >
comparison for each element of
self
and rhs
.
In other words this computes [self.x > rhs.x, self.y > rhs.y, ..]
for all
elements.
Sourcepub fn cmple(self, rhs: Vec3) -> BVec3
pub fn cmple(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a <=
comparison for each element of
self
and rhs
.
In other words this computes [self.x <= rhs.x, self.y <= rhs.y, ..]
for all
elements.
Sourcepub fn cmplt(self, rhs: Vec3) -> BVec3
pub fn cmplt(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a <
comparison for each element of
self
and rhs
.
In other words this computes [self.x < rhs.x, self.y < rhs.y, ..]
for all
elements.
Sourcepub fn abs(self) -> Vec3
pub fn abs(self) -> Vec3
Returns a vector containing the absolute value of each element of self
.
Sourcepub fn signum(self) -> Vec3
pub fn signum(self) -> Vec3
Returns a vector with elements representing the sign of self
.
1.0
if the number is positive,+0.0
orINFINITY
-1.0
if the number is negative,-0.0
orNEG_INFINITY
NAN
if the number isNAN
Sourcepub fn copysign(self, rhs: Vec3) -> Vec3
pub fn copysign(self, rhs: Vec3) -> Vec3
Returns a vector with signs of rhs
and the magnitudes of self
.
Sourcepub fn is_negative_bitmask(self) -> u32
pub fn is_negative_bitmask(self) -> u32
Returns a bitmask with the lowest 3 bits set to the sign bits from the elements of self
.
A negative element results in a 1
bit and a positive element in a 0
bit. Element x
goes
into the first lowest bit, element y
into the second, etc.
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_finite_mask(self) -> BVec3
pub fn is_finite_mask(self) -> BVec3
Performs is_finite
on each element of self, returning a vector mask of the results.
In other words, this computes [x.is_finite(), y.is_finite(), ...]
.
Sourcepub fn is_nan_mask(self) -> BVec3
pub fn is_nan_mask(self) -> BVec3
Performs is_nan
on each element of self, returning a vector mask of the results.
In other words, this computes [x.is_nan(), y.is_nan(), ...]
.
Sourcepub fn length(self) -> f32
pub fn length(self) -> f32
Computes the length of self
.
Examples found in repository?
More examples
301fn move_cars(
302 time: Res<Time>,
303 mut movables: Query<(&mut Transform, &Moves, &Children)>,
304 mut spins: Query<&mut Transform, (Without<Moves>, With<Rotates>)>,
305) {
306 for (mut transform, moves, children) in &mut movables {
307 let time = time.elapsed_secs() * 0.25;
308 let t = time + 0.5 * moves.0;
309 let dx = ops::cos(t);
310 let dz = -ops::sin(3.0 * t);
311 let speed_variation = (dx * dx + dz * dz).sqrt() * 0.15;
312 let t = t + speed_variation;
313 let prev = transform.translation;
314 transform.translation.x = race_track_pos(0.0, t).x;
315 transform.translation.z = race_track_pos(0.0, t).y;
316 transform.translation.y = -0.59;
317 let delta = transform.translation - prev;
318 transform.look_to(delta, Vec3::Y);
319 for child in children.iter() {
320 let Ok(mut wheel) = spins.get_mut(*child) else {
321 continue;
322 };
323 let radius = wheel.scale.x;
324 let circumference = 2.0 * std::f32::consts::PI * radius;
325 let angle = delta.length() / circumference * std::f32::consts::PI * 2.0;
326 wheel.rotate_local_y(angle);
327 }
328 }
329}
128fn move_pointer(
129 // `Single` ensures the system runs ONLY when exactly one matching entity exists.
130 mut player: Single<(&mut Transform, &Player)>,
131 // `Option<Single>` ensures that the system runs ONLY when zero or one matching entity exists.
132 enemy: Option<Single<&Transform, (With<Enemy>, Without<Player>)>>,
133 time: Res<Time>,
134) {
135 let (player_transform, player) = &mut *player;
136 if let Some(enemy_transform) = enemy {
137 // Enemy found, rotate and move towards it.
138 let delta = enemy_transform.translation - player_transform.translation;
139 let distance = delta.length();
140 let front = delta / distance;
141 let up = Vec3::Z;
142 let side = front.cross(up);
143 player_transform.rotation = Quat::from_mat3(&Mat3::from_cols(side, front, up));
144 let max_step = distance - player.min_follow_radius;
145 if 0.0 < max_step {
146 let velocity = (player.speed * time.delta_secs()).min(max_step);
147 player_transform.translation += front * velocity;
148 }
149 } else {
150 // No enemy found, keep searching.
151 player_transform.rotate_axis(Dir3::Z, player.rotation_speed * time.delta_secs());
152 }
153}
126fn scale_down_sphere_proportional_to_cube_travel_distance(
127 cubes: Query<(&Transform, &CubeState), Without<Center>>,
128 mut centers: Query<(&mut Transform, &Center)>,
129) {
130 // First we need to calculate the length of between
131 // the current position of the orbiting cube and the spawn position.
132 let mut distances = 0.0;
133 for (cube_transform, cube_state) in &cubes {
134 distances += (cube_state.start_pos - cube_transform.translation).length();
135 }
136 // Now we use the calculated value to scale the sphere in the center accordingly.
137 for (mut transform, center) in &mut centers {
138 // Calculate the new size from the calculated distances and the centers scale_factor.
139 // Since we want to have the sphere at its max_size at the cubes spawn location we start by
140 // using the max_size as start value and subtract the distances scaled by a scaling factor.
141 let mut new_size: f32 = center.max_size - center.scale_factor * distances;
142
143 // The new size should also not be smaller than the centers min_size.
144 // Therefore the max value out of (new_size, center.min_size) is used.
145 new_size = new_size.max(center.min_size);
146
147 // Now scale the sphere uniformly in all directions using new_size.
148 // Here Vec3:splat is used to create a vector with new_size in x, y and z direction.
149 transform.scale = Vec3::splat(new_size);
150 }
151}
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}
211fn move_camera(
212 keyboard_input: Res<ButtonInput<KeyCode>>,
213 mut mouse_wheel_events: EventReader<MouseWheel>,
214 mut cameras: Query<&mut Transform, With<Camera3d>>,
215) {
216 let (mut zoom_delta, mut theta_delta) = (0.0, 0.0);
217
218 // Process zoom in and out via the keyboard.
219 if keyboard_input.pressed(KeyCode::KeyW) || keyboard_input.pressed(KeyCode::ArrowUp) {
220 zoom_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
221 } else if keyboard_input.pressed(KeyCode::KeyS) || keyboard_input.pressed(KeyCode::ArrowDown) {
222 zoom_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
223 }
224
225 // Process left and right pan via the keyboard.
226 if keyboard_input.pressed(KeyCode::KeyA) || keyboard_input.pressed(KeyCode::ArrowLeft) {
227 theta_delta -= CAMERA_KEYBOARD_PAN_SPEED;
228 } else if keyboard_input.pressed(KeyCode::KeyD) || keyboard_input.pressed(KeyCode::ArrowRight) {
229 theta_delta += CAMERA_KEYBOARD_PAN_SPEED;
230 }
231
232 // Process zoom in and out via the mouse wheel.
233 for event in mouse_wheel_events.read() {
234 zoom_delta -= event.y * CAMERA_MOUSE_MOVEMENT_SPEED;
235 }
236
237 // Update the camera transform.
238 for transform in cameras.iter_mut() {
239 let transform = transform.into_inner();
240
241 let direction = transform.translation.normalize_or_zero();
242 let magnitude = transform.translation.length();
243
244 let new_direction = Mat3::from_rotation_y(theta_delta) * direction;
245 let new_magnitude = (magnitude + zoom_delta).max(MIN_ZOOM_DISTANCE);
246
247 transform.translation = new_direction * new_magnitude;
248 transform.look_at(CAMERA_FOCAL_POINT, Vec3::Y);
249 }
250}
Sourcepub fn length_squared(self) -> f32
pub fn length_squared(self) -> f32
Computes the squared length of self
.
This is faster than length()
as it avoids a square root operation.
Examples found in repository?
122fn interact_bodies(mut query: Query<(&Mass, &GlobalTransform, &mut Acceleration)>) {
123 let mut iter = query.iter_combinations_mut();
124 while let Some([(Mass(m1), transform1, mut acc1), (Mass(m2), transform2, mut acc2)]) =
125 iter.fetch_next()
126 {
127 let delta = transform2.translation() - transform1.translation();
128 let distance_sq: f32 = delta.length_squared();
129
130 let f = GRAVITY_CONSTANT / distance_sq;
131 let force_unit_mass = delta * f;
132 acc1.0 += force_unit_mass * *m2;
133 acc2.0 -= force_unit_mass * *m1;
134 }
135}
More examples
103fn run_camera_controller(
104 time: Res<Time>,
105 mut windows: Query<&mut Window>,
106 accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
107 accumulated_mouse_scroll: Res<AccumulatedMouseScroll>,
108 mouse_button_input: Res<ButtonInput<MouseButton>>,
109 key_input: Res<ButtonInput<KeyCode>>,
110 mut toggle_cursor_grab: Local<bool>,
111 mut mouse_cursor_grab: Local<bool>,
112 mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>,
113) {
114 let dt = time.delta_secs();
115
116 if let Ok((mut transform, mut controller)) = query.get_single_mut() {
117 if !controller.initialized {
118 let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
119 controller.yaw = yaw;
120 controller.pitch = pitch;
121 controller.initialized = true;
122 info!("{}", *controller);
123 }
124 if !controller.enabled {
125 return;
126 }
127
128 let mut scroll = 0.0;
129
130 let amount = match accumulated_mouse_scroll.unit {
131 MouseScrollUnit::Line => accumulated_mouse_scroll.delta.y,
132 MouseScrollUnit::Pixel => accumulated_mouse_scroll.delta.y / 16.0,
133 };
134 scroll += amount;
135 controller.walk_speed += scroll * controller.scroll_factor * controller.walk_speed;
136 controller.run_speed = controller.walk_speed * 3.0;
137
138 // Handle key input
139 let mut axis_input = Vec3::ZERO;
140 if key_input.pressed(controller.key_forward) {
141 axis_input.z += 1.0;
142 }
143 if key_input.pressed(controller.key_back) {
144 axis_input.z -= 1.0;
145 }
146 if key_input.pressed(controller.key_right) {
147 axis_input.x += 1.0;
148 }
149 if key_input.pressed(controller.key_left) {
150 axis_input.x -= 1.0;
151 }
152 if key_input.pressed(controller.key_up) {
153 axis_input.y += 1.0;
154 }
155 if key_input.pressed(controller.key_down) {
156 axis_input.y -= 1.0;
157 }
158
159 let mut cursor_grab_change = false;
160 if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
161 *toggle_cursor_grab = !*toggle_cursor_grab;
162 cursor_grab_change = true;
163 }
164 if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
165 *mouse_cursor_grab = true;
166 cursor_grab_change = true;
167 }
168 if mouse_button_input.just_released(controller.mouse_key_cursor_grab) {
169 *mouse_cursor_grab = false;
170 cursor_grab_change = true;
171 }
172 let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab;
173
174 // Apply movement update
175 if axis_input != Vec3::ZERO {
176 let max_speed = if key_input.pressed(controller.key_run) {
177 controller.run_speed
178 } else {
179 controller.walk_speed
180 };
181 controller.velocity = axis_input.normalize() * max_speed;
182 } else {
183 let friction = controller.friction.clamp(0.0, 1.0);
184 controller.velocity *= 1.0 - friction;
185 if controller.velocity.length_squared() < 1e-6 {
186 controller.velocity = Vec3::ZERO;
187 }
188 }
189 let forward = *transform.forward();
190 let right = *transform.right();
191 transform.translation += controller.velocity.x * dt * right
192 + controller.velocity.y * dt * Vec3::Y
193 + controller.velocity.z * dt * forward;
194
195 // Handle cursor grab
196 if cursor_grab_change {
197 if cursor_grab {
198 for mut window in &mut windows {
199 if !window.focused {
200 continue;
201 }
202
203 window.cursor_options.grab_mode = CursorGrabMode::Locked;
204 window.cursor_options.visible = false;
205 }
206 } else {
207 for mut window in &mut windows {
208 window.cursor_options.grab_mode = CursorGrabMode::None;
209 window.cursor_options.visible = true;
210 }
211 }
212 }
213
214 // Handle mouse input
215 if accumulated_mouse_motion.delta != Vec2::ZERO && cursor_grab {
216 // Apply look update
217 controller.pitch = (controller.pitch
218 - accumulated_mouse_motion.delta.y * RADIANS_PER_DOT * controller.sensitivity)
219 .clamp(-PI / 2., PI / 2.);
220 controller.yaw -=
221 accumulated_mouse_motion.delta.x * RADIANS_PER_DOT * controller.sensitivity;
222 transform.rotation =
223 Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
224 }
225 }
226}
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 distance(self, rhs: Vec3) -> f32
pub fn distance(self, rhs: Vec3) -> f32
Computes the Euclidean distance between two points in space.
Examples found in repository?
417fn handle_keypress(
418 mut commands: Commands,
419 keyboard: Res<ButtonInput<KeyCode>>,
420 mut mode: ResMut<SamplingMode>,
421 mut spawn_mode: ResMut<SpawningMode>,
422 samples: Query<Entity, With<SamplePoint>>,
423 shapes: Res<SampledShapes>,
424 mut spawn_queue: ResMut<SpawnQueue>,
425 mut counter: ResMut<PointCounter>,
426 mut text_menus: Query<&mut Visibility, With<Text>>,
427 mut camera_rig: Single<&mut CameraRig>,
428) {
429 // R => restart, deleting all samples
430 if keyboard.just_pressed(KeyCode::KeyR) {
431 // Don't forget to zero out the counter!
432 counter.0 = 0;
433 for entity in &samples {
434 commands.entity(entity).despawn();
435 }
436 }
437
438 // S => sample once
439 if keyboard.just_pressed(KeyCode::KeyS) {
440 spawn_queue.0 += 1;
441 }
442
443 // D => sample a hundred
444 if keyboard.just_pressed(KeyCode::KeyD) {
445 spawn_queue.0 += 100;
446 }
447
448 // M => toggle mode between interior and boundary.
449 if keyboard.just_pressed(KeyCode::KeyM) {
450 match *mode {
451 SamplingMode::Interior => *mode = SamplingMode::Boundary,
452 SamplingMode::Boundary => *mode = SamplingMode::Interior,
453 }
454 }
455
456 // A => toggle spawning mode between automatic and manual.
457 if keyboard.just_pressed(KeyCode::KeyA) {
458 match *spawn_mode {
459 SpawningMode::Manual => *spawn_mode = SpawningMode::Automatic,
460 SpawningMode::Automatic => *spawn_mode = SpawningMode::Manual,
461 }
462 }
463
464 // Tab => toggle help menu.
465 if keyboard.just_pressed(KeyCode::Tab) {
466 for mut visibility in text_menus.iter_mut() {
467 *visibility = match *visibility {
468 Visibility::Hidden => Visibility::Visible,
469 _ => Visibility::Hidden,
470 };
471 }
472 }
473
474 // +/- => zoom camera.
475 if keyboard.just_pressed(KeyCode::NumpadSubtract) || keyboard.just_pressed(KeyCode::Minus) {
476 camera_rig.distance += MAX_CAMERA_DISTANCE / 15.0;
477 camera_rig.distance = camera_rig
478 .distance
479 .clamp(MIN_CAMERA_DISTANCE, MAX_CAMERA_DISTANCE);
480 }
481
482 if keyboard.just_pressed(KeyCode::NumpadAdd) {
483 camera_rig.distance -= MAX_CAMERA_DISTANCE / 15.0;
484 camera_rig.distance = camera_rig
485 .distance
486 .clamp(MIN_CAMERA_DISTANCE, MAX_CAMERA_DISTANCE);
487 }
488
489 // Arrows => Move camera focus
490 let left = keyboard.just_pressed(KeyCode::ArrowLeft);
491 let right = keyboard.just_pressed(KeyCode::ArrowRight);
492
493 if left || right {
494 let mut closest = 0;
495 let mut closest_distance = f32::MAX;
496 for (i, (_, position)) in shapes.0.iter().enumerate() {
497 let distance = camera_rig.target.distance(*position);
498 if distance < closest_distance {
499 closest = i;
500 closest_distance = distance;
501 }
502 }
503 if closest > 0 && left {
504 camera_rig.target = shapes.0[closest - 1].1;
505 }
506 if closest < shapes.0.len() - 1 && right {
507 camera_rig.target = shapes.0[closest + 1].1;
508 }
509 }
510}
Sourcepub fn distance_squared(self, rhs: Vec3) -> f32
pub fn distance_squared(self, rhs: Vec3) -> f32
Compute the squared euclidean distance between two points in space.
Sourcepub fn div_euclid(self, rhs: Vec3) -> Vec3
pub fn div_euclid(self, rhs: Vec3) -> Vec3
Returns the element-wise quotient of [Euclidean division] of self
by rhs
.
Sourcepub fn rem_euclid(self, rhs: Vec3) -> Vec3
pub fn rem_euclid(self, rhs: Vec3) -> Vec3
Returns the element-wise remainder of Euclidean division of self
by rhs
.
Sourcepub fn normalize(self) -> Vec3
pub fn normalize(self) -> Vec3
Returns self
normalized to length 1.0.
For valid results, self
must be finite and not of length zero, nor very close to zero.
See also Self::try_normalize()
and Self::normalize_or_zero()
.
Panics
Will panic if the resulting normalized vector is not finite when glam_assert
is enabled.
Examples found in repository?
More examples
170fn movement(
171 time: Res<Time>,
172 input: Res<ButtonInput<KeyCode>>,
173 mut query: Query<&mut Transform, With<Sprite>>,
174) {
175 for mut transform in &mut query {
176 let mut direction = Vec3::ZERO;
177 if input.pressed(KeyCode::ArrowLeft) {
178 direction.x -= 1.0;
179 }
180 if input.pressed(KeyCode::ArrowRight) {
181 direction.x += 1.0;
182 }
183 if input.pressed(KeyCode::ArrowUp) {
184 direction.y += 1.0;
185 }
186 if input.pressed(KeyCode::ArrowDown) {
187 direction.y -= 1.0;
188 }
189
190 if direction != Vec3::ZERO {
191 transform.translation += direction.normalize() * SPEED * time.delta_secs();
192 }
193 }
194}
124fn movement(
125 time: Res<Time>,
126 input: Res<ButtonInput<KeyCode>>,
127 mut query: Query<&mut Transform, With<Sprite>>,
128) {
129 for mut transform in &mut query {
130 let mut direction = Vec3::ZERO;
131 if input.pressed(KeyCode::ArrowLeft) {
132 direction.x -= 1.0;
133 }
134 if input.pressed(KeyCode::ArrowRight) {
135 direction.x += 1.0;
136 }
137 if input.pressed(KeyCode::ArrowUp) {
138 direction.y += 1.0;
139 }
140 if input.pressed(KeyCode::ArrowDown) {
141 direction.y -= 1.0;
142 }
143
144 if direction != Vec3::ZERO {
145 transform.translation += direction.normalize() * SPEED * time.delta_secs();
146 }
147 }
148}
91fn movement(
92 time: Res<Time>,
93 input: Res<ButtonInput<KeyCode>>,
94 mut query: Query<&mut Transform, With<Sprite>>,
95) {
96 for mut transform in &mut query {
97 let mut direction = Vec3::ZERO;
98 if input.pressed(KeyCode::ArrowLeft) {
99 direction.x -= 1.0;
100 }
101 if input.pressed(KeyCode::ArrowRight) {
102 direction.x += 1.0;
103 }
104 if input.pressed(KeyCode::ArrowUp) {
105 direction.y += 1.0;
106 }
107 if input.pressed(KeyCode::ArrowDown) {
108 direction.y -= 1.0;
109 }
110
111 if direction != Vec3::ZERO {
112 transform.translation += direction.normalize() * SPEED * time.delta_secs();
113 }
114 }
115}
425 pub fn movement(
426 time: Res<Time>,
427 input: Res<ButtonInput<KeyCode>>,
428 turbo: Option<Res<State<TurboMode>>>,
429 mut query: Query<&mut Transform, With<Sprite>>,
430 ) {
431 for mut transform in &mut query {
432 let mut direction = Vec3::ZERO;
433 if input.pressed(KeyCode::ArrowLeft) {
434 direction.x -= 1.0;
435 }
436 if input.pressed(KeyCode::ArrowRight) {
437 direction.x += 1.0;
438 }
439 if input.pressed(KeyCode::ArrowUp) {
440 direction.y += 1.0;
441 }
442 if input.pressed(KeyCode::ArrowDown) {
443 direction.y -= 1.0;
444 }
445
446 if direction != Vec3::ZERO {
447 transform.translation += direction.normalize()
448 * if turbo.is_some() { TURBO_SPEED } else { SPEED }
449 * time.delta_secs();
450 }
451 }
452 }
447fn handle_mouse_clicks(
448 buttons: Res<ButtonInput<MouseButton>>,
449 windows: Query<&Window, With<PrimaryWindow>>,
450 cameras: Query<(&Camera, &GlobalTransform)>,
451 mut main_objects: Query<&mut Transform, With<MainObject>>,
452) {
453 if !buttons.pressed(MouseButton::Left) {
454 return;
455 }
456 let Some(mouse_position) = windows.iter().next().and_then(Window::cursor_position) else {
457 return;
458 };
459 let Some((camera, camera_transform)) = cameras.iter().next() else {
460 return;
461 };
462
463 // Figure out where the user clicked on the plane.
464 let Ok(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
465 return;
466 };
467 let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else {
468 return;
469 };
470 let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;
471
472 // Move all the main objeccts.
473 for mut transform in main_objects.iter_mut() {
474 transform.translation = vec3(
475 plane_intersection.x,
476 transform.translation.y,
477 plane_intersection.z,
478 );
479 }
480}
Sourcepub fn try_normalize(self) -> Option<Vec3>
pub fn try_normalize(self) -> Option<Vec3>
Returns self
normalized to length 1.0 if possible, else returns None
.
In particular, if the input is zero (or very close to zero), or non-finite,
the result of this operation will be None
.
See also Self::normalize_or_zero()
.
Examples found in repository?
614fn rotate_primitive_3d_meshes(
615 mut primitives_3d: Query<
616 (&mut Transform, &ViewVisibility),
617 (With<PrimitiveData>, With<MeshDim3>),
618 >,
619 time: Res<Time>,
620) {
621 let rotation_3d = Quat::from_rotation_arc(
622 Vec3::Z,
623 Vec3::new(
624 ops::sin(time.elapsed_secs()),
625 ops::cos(time.elapsed_secs()),
626 ops::sin(time.elapsed_secs()) * 0.5,
627 )
628 .try_normalize()
629 .unwrap_or(Vec3::Z),
630 );
631 primitives_3d
632 .iter_mut()
633 .filter(|(_, vis)| vis.get())
634 .for_each(|(mut transform, _)| {
635 transform.rotation = rotation_3d;
636 });
637}
638
639fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
640 const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
641 let rotation = Quat::from_rotation_arc(
642 Vec3::Z,
643 Vec3::new(
644 ops::sin(time.elapsed_secs()),
645 ops::cos(time.elapsed_secs()),
646 ops::sin(time.elapsed_secs()) * 0.5,
647 )
648 .try_normalize()
649 .unwrap_or(Vec3::Z),
650 );
651 let isometry = Isometry3d::new(POSITION, rotation);
652 let color = Color::WHITE;
653 let resolution = 10;
654
655 match state.get() {
656 PrimitiveSelected::RectangleAndCuboid => {
657 gizmos.primitive_3d(&CUBOID, isometry, color);
658 }
659 PrimitiveSelected::CircleAndSphere => drop(
660 gizmos
661 .primitive_3d(&SPHERE, isometry, color)
662 .resolution(resolution),
663 ),
664 PrimitiveSelected::Ellipse => {}
665 PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, isometry, color),
666 PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, isometry, color)),
667 PrimitiveSelected::Line => gizmos.primitive_3d(&LINE3D, isometry, color),
668 PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, isometry, color),
669 PrimitiveSelected::Polyline => gizmos.primitive_3d(&POLYLINE_3D, isometry, color),
670 PrimitiveSelected::Polygon => {}
671 PrimitiveSelected::RegularPolygon => {}
672 PrimitiveSelected::Capsule => drop(
673 gizmos
674 .primitive_3d(&CAPSULE_3D, isometry, color)
675 .resolution(resolution),
676 ),
677 PrimitiveSelected::Cylinder => drop(
678 gizmos
679 .primitive_3d(&CYLINDER, isometry, color)
680 .resolution(resolution),
681 ),
682 PrimitiveSelected::Cone => drop(
683 gizmos
684 .primitive_3d(&CONE, isometry, color)
685 .resolution(resolution),
686 ),
687 PrimitiveSelected::ConicalFrustum => {
688 gizmos.primitive_3d(&CONICAL_FRUSTUM, isometry, color);
689 }
690
691 PrimitiveSelected::Torus => drop(
692 gizmos
693 .primitive_3d(&TORUS, isometry, color)
694 .minor_resolution(resolution)
695 .major_resolution(resolution),
696 ),
697 PrimitiveSelected::Tetrahedron => {
698 gizmos.primitive_3d(&TETRAHEDRON, isometry, color);
699 }
700
701 PrimitiveSelected::Arc => {}
702 PrimitiveSelected::CircularSector => {}
703 PrimitiveSelected::CircularSegment => {}
704 }
705}
Sourcepub fn normalize_or(self, fallback: Vec3) -> Vec3
pub fn normalize_or(self, fallback: Vec3) -> Vec3
Returns self
normalized to length 1.0 if possible, else returns a
fallback value.
In particular, if the input is zero (or very close to zero), or non-finite, the result of this operation will be the fallback value.
See also Self::try_normalize()
.
Sourcepub fn normalize_or_zero(self) -> Vec3
pub fn normalize_or_zero(self) -> Vec3
Returns self
normalized to length 1.0 if possible, else returns zero.
In particular, if the input is zero (or very close to zero), or non-finite, the result of this operation will be zero.
See also Self::try_normalize()
.
Examples found in repository?
167fn handle_input(
168 keyboard_input: Res<ButtonInput<KeyCode>>,
169 mut query: Query<(&mut AccumulatedInput, &mut Velocity)>,
170) {
171 /// Since Bevy's default 2D camera setup is scaled such that
172 /// one unit is one pixel, you can think of this as
173 /// "How many pixels per second should the player move?"
174 const SPEED: f32 = 210.0;
175 for (mut input, mut velocity) in query.iter_mut() {
176 if keyboard_input.pressed(KeyCode::KeyW) {
177 input.y += 1.0;
178 }
179 if keyboard_input.pressed(KeyCode::KeyS) {
180 input.y -= 1.0;
181 }
182 if keyboard_input.pressed(KeyCode::KeyA) {
183 input.x -= 1.0;
184 }
185 if keyboard_input.pressed(KeyCode::KeyD) {
186 input.x += 1.0;
187 }
188
189 // Need to normalize and scale because otherwise
190 // diagonal movement would be faster than horizontal or vertical movement.
191 // This effectively averages the accumulated input.
192 velocity.0 = input.extend(0.0).normalize_or_zero() * SPEED;
193 }
194}
More examples
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}
211fn move_camera(
212 keyboard_input: Res<ButtonInput<KeyCode>>,
213 mut mouse_wheel_events: EventReader<MouseWheel>,
214 mut cameras: Query<&mut Transform, With<Camera3d>>,
215) {
216 let (mut zoom_delta, mut theta_delta) = (0.0, 0.0);
217
218 // Process zoom in and out via the keyboard.
219 if keyboard_input.pressed(KeyCode::KeyW) || keyboard_input.pressed(KeyCode::ArrowUp) {
220 zoom_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
221 } else if keyboard_input.pressed(KeyCode::KeyS) || keyboard_input.pressed(KeyCode::ArrowDown) {
222 zoom_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
223 }
224
225 // Process left and right pan via the keyboard.
226 if keyboard_input.pressed(KeyCode::KeyA) || keyboard_input.pressed(KeyCode::ArrowLeft) {
227 theta_delta -= CAMERA_KEYBOARD_PAN_SPEED;
228 } else if keyboard_input.pressed(KeyCode::KeyD) || keyboard_input.pressed(KeyCode::ArrowRight) {
229 theta_delta += CAMERA_KEYBOARD_PAN_SPEED;
230 }
231
232 // Process zoom in and out via the mouse wheel.
233 for event in mouse_wheel_events.read() {
234 zoom_delta -= event.y * CAMERA_MOUSE_MOVEMENT_SPEED;
235 }
236
237 // Update the camera transform.
238 for transform in cameras.iter_mut() {
239 let transform = transform.into_inner();
240
241 let direction = transform.translation.normalize_or_zero();
242 let magnitude = transform.translation.length();
243
244 let new_direction = Mat3::from_rotation_y(theta_delta) * direction;
245 let new_magnitude = (magnitude + zoom_delta).max(MIN_ZOOM_DISTANCE);
246
247 transform.translation = new_direction * new_magnitude;
248 transform.look_at(CAMERA_FOCAL_POINT, Vec3::Y);
249 }
250}
Sourcepub fn is_normalized(self) -> bool
pub fn is_normalized(self) -> bool
Returns whether self
is length 1.0
or not.
Uses a precision threshold of approximately 1e-4
.
Sourcepub fn project_onto(self, rhs: Vec3) -> Vec3
pub fn project_onto(self, rhs: Vec3) -> Vec3
Returns the vector projection of self
onto rhs
.
rhs
must be of non-zero length.
§Panics
Will panic if rhs
is zero length when glam_assert
is enabled.
Sourcepub fn reject_from(self, rhs: Vec3) -> Vec3
pub fn reject_from(self, rhs: Vec3) -> Vec3
Returns the vector rejection of self
from rhs
.
The vector rejection is the vector perpendicular to the projection of self
onto
rhs
, in rhs words the result of self - self.project_onto(rhs)
.
rhs
must be of non-zero length.
§Panics
Will panic if rhs
has a length of zero when glam_assert
is enabled.
Sourcepub fn project_onto_normalized(self, rhs: Vec3) -> Vec3
pub fn project_onto_normalized(self, rhs: Vec3) -> Vec3
Returns the vector projection of self
onto rhs
.
rhs
must be normalized.
§Panics
Will panic if rhs
is not normalized when glam_assert
is enabled.
Sourcepub fn reject_from_normalized(self, rhs: Vec3) -> Vec3
pub fn reject_from_normalized(self, rhs: Vec3) -> Vec3
Returns the vector rejection of self
from rhs
.
The vector rejection is the vector perpendicular to the projection of self
onto
rhs
, in rhs words the result of self - self.project_onto(rhs)
.
rhs
must be normalized.
§Panics
Will panic if rhs
is not normalized when glam_assert
is enabled.
Examples found in repository?
40fn observe_on_step(
41 trigger: Trigger<OnStep>,
42 particle: Res<ParticleAssets>,
43 mut commands: Commands,
44 transforms: Query<&GlobalTransform>,
45) {
46 let translation = transforms.get(trigger.entity()).unwrap().translation();
47 let mut rng = thread_rng();
48 // Spawn a bunch of particles.
49 for _ in 0..14 {
50 let horizontal = rng.gen::<Dir2>() * rng.gen_range(8.0..12.0);
51 let vertical = rng.gen_range(0.0..4.0);
52 let size = rng.gen_range(0.2..1.0);
53 commands.queue(spawn_particle(
54 particle.mesh.clone(),
55 particle.material.clone(),
56 translation.reject_from_normalized(Vec3::Y),
57 rng.gen_range(0.2..0.6),
58 size,
59 Vec3::new(horizontal.x, vertical, horizontal.y) * 10.0,
60 ));
61 }
62}
Sourcepub fn round(self) -> Vec3
pub fn round(self) -> Vec3
Returns a vector containing the nearest integer to a number for each element of self
.
Round half-way cases away from 0.0.
Sourcepub fn floor(self) -> Vec3
pub fn floor(self) -> Vec3
Returns a vector containing the largest integer less than or equal to a number for each
element of self
.
Examples found in repository?
65fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
66 for (mut transform, mut cube) in &mut cubes {
67 // If an entity scaled beyond the maximum of its size in any dimension
68 // the scaling vector is flipped so the scaling is gradually reverted.
69 // Additionally, to ensure the condition does not trigger again we floor the elements to
70 // their next full value, which should be max_element_size at max.
71 if transform.scale.max_element() > cube.max_element_size {
72 cube.scale_direction *= -1.0;
73 transform.scale = transform.scale.floor();
74 }
75 // If an entity scaled beyond the minimum of its size in any dimension
76 // the scaling vector is also flipped.
77 // Additionally the Values are ceiled to be min_element_size at least
78 // and the scale direction is flipped.
79 // This way the entity will change the dimension in which it is scaled any time it
80 // reaches its min_element_size.
81 if transform.scale.min_element() < cube.min_element_size {
82 cube.scale_direction *= -1.0;
83 transform.scale = transform.scale.ceil();
84 cube.scale_direction = cube.scale_direction.zxy();
85 }
86 }
87}
Sourcepub fn ceil(self) -> Vec3
pub fn ceil(self) -> Vec3
Returns a vector containing the smallest integer greater than or equal to a number for
each element of self
.
Examples found in repository?
65fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
66 for (mut transform, mut cube) in &mut cubes {
67 // If an entity scaled beyond the maximum of its size in any dimension
68 // the scaling vector is flipped so the scaling is gradually reverted.
69 // Additionally, to ensure the condition does not trigger again we floor the elements to
70 // their next full value, which should be max_element_size at max.
71 if transform.scale.max_element() > cube.max_element_size {
72 cube.scale_direction *= -1.0;
73 transform.scale = transform.scale.floor();
74 }
75 // If an entity scaled beyond the minimum of its size in any dimension
76 // the scaling vector is also flipped.
77 // Additionally the Values are ceiled to be min_element_size at least
78 // and the scale direction is flipped.
79 // This way the entity will change the dimension in which it is scaled any time it
80 // reaches its min_element_size.
81 if transform.scale.min_element() < cube.min_element_size {
82 cube.scale_direction *= -1.0;
83 transform.scale = transform.scale.ceil();
84 cube.scale_direction = cube.scale_direction.zxy();
85 }
86 }
87}
Sourcepub fn trunc(self) -> Vec3
pub fn trunc(self) -> Vec3
Returns a vector containing the integer part each element of self
. This means numbers are
always truncated towards zero.
Sourcepub fn fract(self) -> Vec3
pub fn fract(self) -> Vec3
Returns a vector containing the fractional part of the vector as self - self.trunc()
.
Note that this differs from the GLSL implementation of fract
which returns
self - self.floor()
.
Note that this is fast but not precise for large numbers.
Sourcepub fn fract_gl(self) -> Vec3
pub fn fract_gl(self) -> Vec3
Returns a vector containing the fractional part of the vector as self - self.floor()
.
Note that this differs from the Rust implementation of fract
which returns
self - self.trunc()
.
Note that this is fast but not precise for large numbers.
Sourcepub fn exp(self) -> Vec3
pub fn exp(self) -> Vec3
Returns a vector containing e^self
(the exponential function) for each element of
self
.
Sourcepub fn powf(self, n: f32) -> Vec3
pub fn powf(self, n: f32) -> Vec3
Returns a vector containing each element of self
raised to the power of n
.
Sourcepub fn recip(self) -> Vec3
pub fn recip(self) -> Vec3
Returns a vector containing the reciprocal 1.0/n
of each element of self
.
Sourcepub fn lerp(self, rhs: Vec3, s: f32) -> Vec3
pub fn lerp(self, rhs: Vec3, s: f32) -> Vec3
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
. When s
is outside of range [0, 1]
, the result is linearly
extrapolated.
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}
224fn interpolate_rendered_transform(
225 fixed_time: Res<Time<Fixed>>,
226 mut query: Query<(
227 &mut Transform,
228 &PhysicalTranslation,
229 &PreviousPhysicalTranslation,
230 )>,
231) {
232 for (mut transform, current_physical_translation, previous_physical_translation) in
233 query.iter_mut()
234 {
235 let previous = previous_physical_translation.0;
236 let current = current_physical_translation.0;
237 // The overstep fraction is a value between 0 and 1 that tells us how far we are between two fixed timesteps.
238 let alpha = fixed_time.overstep_fraction();
239
240 let rendered_translation = previous.lerp(current, alpha);
241 transform.translation = rendered_translation;
242 }
243}
267fn focus_camera(
268 time: Res<Time>,
269 mut game: ResMut<Game>,
270 mut transforms: ParamSet<(Query<&mut Transform, With<Camera3d>>, Query<&Transform>)>,
271) {
272 const SPEED: f32 = 2.0;
273 // if there is both a player and a bonus, target the mid-point of them
274 if let (Some(player_entity), Some(bonus_entity)) = (game.player.entity, game.bonus.entity) {
275 let transform_query = transforms.p1();
276 if let (Ok(player_transform), Ok(bonus_transform)) = (
277 transform_query.get(player_entity),
278 transform_query.get(bonus_entity),
279 ) {
280 game.camera_should_focus = player_transform
281 .translation
282 .lerp(bonus_transform.translation, 0.5);
283 }
284 // otherwise, if there is only a player, target the player
285 } else if let Some(player_entity) = game.player.entity {
286 if let Ok(player_transform) = transforms.p1().get(player_entity) {
287 game.camera_should_focus = player_transform.translation;
288 }
289 // otherwise, target the middle
290 } else {
291 game.camera_should_focus = Vec3::from(RESET_FOCUS);
292 }
293 // calculate the camera motion based on the difference between where the camera is looking
294 // and where it should be looking; the greater the distance, the faster the motion;
295 // smooth out the camera movement using the frame time
296 let mut camera_motion = game.camera_should_focus - game.camera_is_focus;
297 if camera_motion.length() > 0.2 {
298 camera_motion *= SPEED * time.delta_secs();
299 // set the new camera's actual focus
300 game.camera_is_focus += camera_motion;
301 }
302 // look at that new camera's actual focus
303 for mut transform in transforms.p0().iter_mut() {
304 *transform = transform.looking_at(game.camera_is_focus, Vec3::Y);
305 }
306}
Sourcepub fn move_towards(&self, rhs: Vec3, d: f32) -> Vec3
pub fn move_towards(&self, rhs: Vec3, d: f32) -> Vec3
Moves towards rhs
based on the value d
.
When d
is 0.0
, the result will be equal to self
. When d
is equal to
self.distance(rhs)
, the result will be equal to rhs
. Will not go past rhs
.
Sourcepub fn midpoint(self, rhs: Vec3) -> Vec3
pub fn midpoint(self, rhs: Vec3) -> Vec3
Calculates the midpoint between self
and rhs
.
The midpoint is the average of, or halfway point between, two vectors.
a.midpoint(b)
should yield the same result as a.lerp(b, 0.5)
while being slightly cheaper to compute.
Sourcepub fn abs_diff_eq(self, rhs: Vec3, max_abs_diff: f32) -> bool
pub fn abs_diff_eq(self, rhs: Vec3, 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 vectors 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 clamp_length(self, min: f32, max: f32) -> Vec3
pub fn clamp_length(self, min: f32, max: f32) -> Vec3
Returns a vector with a length no less than min
and no more than max
.
§Panics
Will panic if min
is greater than max
, or if either min
or max
is negative, when glam_assert
is enabled.
Sourcepub fn clamp_length_max(self, max: f32) -> Vec3
pub fn clamp_length_max(self, max: f32) -> Vec3
Returns a vector with a length no more than max
.
§Panics
Will panic if max
is negative when glam_assert
is enabled.
Sourcepub fn clamp_length_min(self, min: f32) -> Vec3
pub fn clamp_length_min(self, min: f32) -> Vec3
Returns a vector with a length no less than min
.
§Panics
Will panic if min
is negative when glam_assert
is enabled.
Sourcepub fn mul_add(self, a: Vec3, b: Vec3) -> Vec3
pub fn mul_add(self, a: Vec3, b: Vec3) -> Vec3
Fused multiply-add. Computes (self * a) + b
element-wise with only one rounding
error, yielding a more accurate result than an unfused multiply-add.
Using mul_add
may be more performant than an unfused multiply-add if the target
architecture has a dedicated fma CPU instruction. However, this is not always true,
and will be heavily dependant on designing algorithms with specific target hardware in
mind.
Sourcepub fn reflect(self, normal: Vec3) -> Vec3
pub fn reflect(self, normal: Vec3) -> Vec3
Returns the reflection vector for a given incident vector self
and surface normal
normal
.
normal
must be normalized.
§Panics
Will panic if normal
is not normalized when glam_assert
is enabled.
Examples found in repository?
48fn bounce_ray(mut ray: Ray3d, ray_cast: &mut MeshRayCast, gizmos: &mut Gizmos, color: Color) {
49 let mut intersections = Vec::with_capacity(MAX_BOUNCES + 1);
50 intersections.push((ray.origin, Color::srgb(30.0, 0.0, 0.0)));
51
52 for i in 0..MAX_BOUNCES {
53 // Cast the ray and get the first hit
54 let Some((_, hit)) = ray_cast.cast_ray(ray, &RayCastSettings::default()).first() else {
55 break;
56 };
57
58 // Draw the point of intersection and add it to the list
59 let brightness = 1.0 + 10.0 * (1.0 - i as f32 / MAX_BOUNCES as f32);
60 intersections.push((hit.point, Color::BLACK.mix(&color, brightness)));
61 gizmos.sphere(hit.point, 0.005, Color::BLACK.mix(&color, brightness * 2.0));
62
63 // Reflect the ray off of the surface
64 ray.direction = Dir3::new(ray.direction.reflect(hit.normal)).unwrap();
65 ray.origin = hit.point + ray.direction * 1e-6;
66 }
67 gizmos.linestrip_gradient(intersections);
68}
Sourcepub fn refract(self, normal: Vec3, eta: f32) -> Vec3
pub fn refract(self, normal: Vec3, eta: f32) -> Vec3
Returns the refraction direction for a given incident vector self
, surface normal
normal
and ratio of indices of refraction, eta
. When total internal reflection occurs,
a zero vector will be returned.
self
and normal
must be normalized.
§Panics
Will panic if self
or normal
is not normalized when glam_assert
is enabled.
Sourcepub fn angle_between(self, rhs: Vec3) -> f32
pub fn angle_between(self, rhs: Vec3) -> f32
Returns the angle (in radians) between two vectors in the range [0, +π]
.
The inputs do not need to be unit vectors however they must be non-zero.
Sourcepub fn any_orthogonal_vector(&self) -> Vec3
pub fn any_orthogonal_vector(&self) -> Vec3
Returns some vector that is orthogonal to the given one.
The input vector must be finite and non-zero.
The output vector is not necessarily unit length. For that use
Self::any_orthonormal_vector()
instead.
Sourcepub fn any_orthonormal_vector(&self) -> Vec3
pub fn any_orthonormal_vector(&self) -> Vec3
Returns any unit vector that is orthogonal to the given one.
The input vector must be unit length.
§Panics
Will panic if self
is not normalized when glam_assert
is enabled.
Sourcepub fn any_orthonormal_pair(&self) -> (Vec3, Vec3)
pub fn any_orthonormal_pair(&self) -> (Vec3, Vec3)
Given a unit vector return two other vectors that together form an orthonormal basis. That is, all three vectors are orthogonal to each other and are normalized.
§Panics
Will panic if self
is not normalized when glam_assert
is enabled.
Sourcepub fn as_i16vec3(&self) -> I16Vec3
pub fn as_i16vec3(&self) -> I16Vec3
Casts all elements of self
to i16
.
Sourcepub fn as_u16vec3(&self) -> U16Vec3
pub fn as_u16vec3(&self) -> U16Vec3
Casts all elements of self
to u16
.
Sourcepub fn as_i64vec3(&self) -> I64Vec3
pub fn as_i64vec3(&self) -> I64Vec3
Casts all elements of self
to i64
.
Sourcepub fn as_u64vec3(&self) -> U64Vec3
pub fn as_u64vec3(&self) -> U64Vec3
Casts all elements of self
to u64
.
Trait Implementations§
Source§impl AddAssign<&Vec3> for Vec3
impl AddAssign<&Vec3> for Vec3
Source§fn add_assign(&mut self, rhs: &Vec3)
fn add_assign(&mut self, rhs: &Vec3)
+=
operation. Read moreSource§impl AddAssign<&f32> for Vec3
impl AddAssign<&f32> for Vec3
Source§fn add_assign(&mut self, rhs: &f32)
fn add_assign(&mut self, rhs: &f32)
+=
operation. Read moreSource§impl AddAssign<f32> for Vec3
impl AddAssign<f32> for Vec3
Source§fn add_assign(&mut self, rhs: f32)
fn add_assign(&mut self, rhs: f32)
+=
operation. Read moreSource§impl AddAssign for Vec3
impl AddAssign for Vec3
Source§fn add_assign(&mut self, rhs: Vec3)
fn add_assign(&mut self, rhs: Vec3)
+=
operation. Read moreSource§impl Animatable for Vec3
impl Animatable for Vec3
Source§impl AsMutVectorParts<f32, 3> for Vec3
impl AsMutVectorParts<f32, 3> for Vec3
fn as_mut_parts(&mut self) -> &mut [f32; 3]
Source§impl AsRefVectorParts<f32, 3> for Vec3
impl AsRefVectorParts<f32, 3> for Vec3
fn as_ref_parts(&self) -> &[f32; 3]
Source§impl CreateFrom for Vec3
impl CreateFrom for Vec3
Source§impl<'de> Deserialize<'de> for Vec3
Deserialize expects a sequence of 3 values.
impl<'de> Deserialize<'de> for Vec3
Deserialize expects a sequence of 3 values.
Source§fn deserialize<D>(
deserializer: D,
) -> Result<Vec3, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<Vec3, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl Distribution<Vec3> for UniformMeshSampler
impl Distribution<Vec3> for UniformMeshSampler
Source§impl DivAssign<&Vec3> for Vec3
impl DivAssign<&Vec3> for Vec3
Source§fn div_assign(&mut self, rhs: &Vec3)
fn div_assign(&mut self, rhs: &Vec3)
/=
operation. Read moreSource§impl DivAssign<&f32> for Vec3
impl DivAssign<&f32> for Vec3
Source§fn div_assign(&mut self, rhs: &f32)
fn div_assign(&mut self, rhs: &f32)
/=
operation. Read moreSource§impl DivAssign<f32> for Vec3
impl DivAssign<f32> for Vec3
Source§fn div_assign(&mut self, rhs: f32)
fn div_assign(&mut self, rhs: f32)
/=
operation. Read moreSource§impl DivAssign for Vec3
impl DivAssign for Vec3
Source§fn div_assign(&mut self, rhs: Vec3)
fn div_assign(&mut self, rhs: Vec3)
/=
operation. Read moreSource§impl From<Vec3> for Isometry3d
impl From<Vec3> for Isometry3d
Source§fn from(translation: Vec3) -> Isometry3d
fn from(translation: Vec3) -> Isometry3d
Source§impl FromIterator<Vec3> for BoxedPolyline3d
impl FromIterator<Vec3> for BoxedPolyline3d
Source§fn from_iter<I>(iter: I) -> BoxedPolyline3dwhere
I: IntoIterator<Item = Vec3>,
fn from_iter<I>(iter: I) -> BoxedPolyline3dwhere
I: IntoIterator<Item = Vec3>,
Source§impl<const N: usize> FromIterator<Vec3> for Polyline3d<N>
impl<const N: usize> FromIterator<Vec3> for Polyline3d<N>
Source§fn from_iter<I>(iter: I) -> Polyline3d<N>where
I: IntoIterator<Item = Vec3>,
fn from_iter<I>(iter: I) -> Polyline3d<N>where
I: IntoIterator<Item = Vec3>,
Source§impl FromReflect for Vec3
impl FromReflect for Vec3
Source§fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Vec3>
fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Vec3>
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 FromVectorParts<f32, 3> for Vec3
impl FromVectorParts<f32, 3> for Vec3
Source§impl GetOwnership for &Vec3
impl GetOwnership for &Vec3
Source§impl GetOwnership for &mut Vec3
impl GetOwnership for &mut Vec3
Source§impl GetOwnership for Vec3
impl GetOwnership for Vec3
Source§impl GetTypeRegistration for Vec3
impl GetTypeRegistration for Vec3
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 &Vec3
impl IntoReturn for &Vec3
Source§impl IntoReturn for &mut Vec3
impl IntoReturn for &mut Vec3
Source§impl IntoReturn for Vec3
impl IntoReturn for Vec3
Source§impl Mul<Vec3> for GlobalTransform
impl Mul<Vec3> for GlobalTransform
Source§impl Mul<Vec3> for Isometry3d
impl Mul<Vec3> for Isometry3d
Source§impl MulAssign<&Vec3> for Vec3
impl MulAssign<&Vec3> for Vec3
Source§fn mul_assign(&mut self, rhs: &Vec3)
fn mul_assign(&mut self, rhs: &Vec3)
*=
operation. Read moreSource§impl MulAssign<&f32> for Vec3
impl MulAssign<&f32> for Vec3
Source§fn mul_assign(&mut self, rhs: &f32)
fn mul_assign(&mut self, rhs: &f32)
*=
operation. Read moreSource§impl MulAssign<f32> for Vec3
impl MulAssign<f32> for Vec3
Source§fn mul_assign(&mut self, rhs: f32)
fn mul_assign(&mut self, rhs: f32)
*=
operation. Read moreSource§impl MulAssign for Vec3
impl MulAssign for Vec3
Source§fn mul_assign(&mut self, rhs: Vec3)
fn mul_assign(&mut self, rhs: Vec3)
*=
operation. Read moreSource§impl NormedVectorSpace for Vec3
impl NormedVectorSpace for Vec3
Source§fn norm_squared(self) -> f32
fn norm_squared(self) -> f32
NormedVectorSpace::norm
.Source§fn distance(self, rhs: Self) -> f32
fn distance(self, rhs: Self) -> f32
Source§fn distance_squared(self, rhs: Self) -> f32
fn distance_squared(self, rhs: Self) -> f32
NormedVectorSpace::distance
.Source§impl PartialReflect for Vec3
impl PartialReflect for Vec3
Source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Source§fn clone_value(&self) -> Box<dyn PartialReflect>
fn clone_value(&self) -> Box<dyn PartialReflect>
Reflect
trait object. Read moreSource§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<Vec3>) -> ReflectOwned
fn reflect_owned(self: Box<Vec3>) -> ReflectOwned
Source§fn try_into_reflect(
self: Box<Vec3>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<Vec3>, ) -> 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<Vec3>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<Vec3>) -> 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 apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
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 Reflect for Vec3
impl Reflect for Vec3
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<Vec3>) -> Box<dyn Reflect>
fn into_reflect(self: Box<Vec3>) -> 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 RemAssign<&Vec3> for Vec3
impl RemAssign<&Vec3> for Vec3
Source§fn rem_assign(&mut self, rhs: &Vec3)
fn rem_assign(&mut self, rhs: &Vec3)
%=
operation. Read moreSource§impl RemAssign<&f32> for Vec3
impl RemAssign<&f32> for Vec3
Source§fn rem_assign(&mut self, rhs: &f32)
fn rem_assign(&mut self, rhs: &f32)
%=
operation. Read moreSource§impl RemAssign<f32> for Vec3
impl RemAssign<f32> for Vec3
Source§fn rem_assign(&mut self, rhs: f32)
fn rem_assign(&mut self, rhs: f32)
%=
operation. Read moreSource§impl RemAssign for Vec3
impl RemAssign for Vec3
Source§fn rem_assign(&mut self, rhs: Vec3)
fn rem_assign(&mut self, rhs: Vec3)
%=
operation. Read moreSource§impl Serialize for Vec3
Serialize as a sequence of 3 values.
impl Serialize for Vec3
Serialize as a sequence of 3 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 ShaderSize for Vec3where
f32: ShaderSize,
impl ShaderSize for Vec3where
f32: ShaderSize,
Source§const SHADER_SIZE: NonZero<u64> = _
const SHADER_SIZE: NonZero<u64> = _
ShaderType::min_size
)Source§impl ShaderType for Vec3where
f32: ShaderSize,
impl ShaderType for Vec3where
f32: ShaderSize,
Source§fn assert_uniform_compat()
fn assert_uniform_compat()
Self
meets the requirements of the
uniform address space restrictions on stored values and the
uniform address space layout constraints Read moreSource§impl Struct for Vec3
impl Struct for Vec3
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<'_> ⓘ
Source§fn clone_dynamic(&self) -> DynamicStruct
fn clone_dynamic(&self) -> DynamicStruct
DynamicStruct
.Source§fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
None
if TypeInfo
is not available.Source§impl SubAssign<&Vec3> for Vec3
impl SubAssign<&Vec3> for Vec3
Source§fn sub_assign(&mut self, rhs: &Vec3)
fn sub_assign(&mut self, rhs: &Vec3)
-=
operation. Read moreSource§impl SubAssign<&f32> for Vec3
impl SubAssign<&f32> for Vec3
Source§fn sub_assign(&mut self, rhs: &f32)
fn sub_assign(&mut self, rhs: &f32)
-=
operation. Read moreSource§impl SubAssign<f32> for Vec3
impl SubAssign<f32> for Vec3
Source§fn sub_assign(&mut self, rhs: f32)
fn sub_assign(&mut self, rhs: f32)
-=
operation. Read moreSource§impl SubAssign for Vec3
impl SubAssign for Vec3
Source§fn sub_assign(&mut self, rhs: Vec3)
fn sub_assign(&mut self, rhs: Vec3)
-=
operation. Read moreSource§impl TypePath for Vec3
impl TypePath for Vec3
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>
Source§impl Vec3Swizzles for Vec3
impl Vec3Swizzles for Vec3
type Vec2 = Vec2
type Vec4 = Vec4
fn xx(self) -> Vec2
fn xy(self) -> Vec2
fn xz(self) -> Vec2
fn yx(self) -> Vec2
fn yy(self) -> Vec2
fn yz(self) -> Vec2
fn zx(self) -> Vec2
fn zy(self) -> Vec2
fn zz(self) -> Vec2
fn xxx(self) -> Vec3
fn xxy(self) -> Vec3
fn xxz(self) -> Vec3
fn xyx(self) -> Vec3
fn xyy(self) -> Vec3
fn xzx(self) -> Vec3
fn xzy(self) -> Vec3
fn xzz(self) -> Vec3
fn yxx(self) -> Vec3
fn yxy(self) -> Vec3
fn yxz(self) -> Vec3
fn yyx(self) -> Vec3
fn yyy(self) -> Vec3
fn yyz(self) -> Vec3
fn yzx(self) -> Vec3
fn yzy(self) -> Vec3
fn yzz(self) -> Vec3
fn zxx(self) -> Vec3
fn zxy(self) -> Vec3
fn zxz(self) -> Vec3
fn zyx(self) -> Vec3
fn zyy(self) -> Vec3
fn zyz(self) -> Vec3
fn zzx(self) -> Vec3
fn zzy(self) -> Vec3
fn zzz(self) -> Vec3
fn xxxx(self) -> Vec4
fn xxxy(self) -> Vec4
fn xxxz(self) -> Vec4
fn xxyx(self) -> Vec4
fn xxyy(self) -> Vec4
fn xxyz(self) -> Vec4
fn xxzx(self) -> Vec4
fn xxzy(self) -> Vec4
fn xxzz(self) -> Vec4
fn xyxx(self) -> Vec4
fn xyxy(self) -> Vec4
fn xyxz(self) -> Vec4
fn xyyx(self) -> Vec4
fn xyyy(self) -> Vec4
fn xyyz(self) -> Vec4
fn xyzx(self) -> Vec4
fn xyzy(self) -> Vec4
fn xyzz(self) -> Vec4
fn xzxx(self) -> Vec4
fn xzxy(self) -> Vec4
fn xzxz(self) -> Vec4
fn xzyx(self) -> Vec4
fn xzyy(self) -> Vec4
fn xzyz(self) -> Vec4
fn xzzx(self) -> Vec4
fn xzzy(self) -> Vec4
fn xzzz(self) -> Vec4
fn yxxx(self) -> Vec4
fn yxxy(self) -> Vec4
fn yxxz(self) -> Vec4
fn yxyx(self) -> Vec4
fn yxyy(self) -> Vec4
fn yxyz(self) -> Vec4
fn yxzx(self) -> Vec4
fn yxzy(self) -> Vec4
fn yxzz(self) -> Vec4
fn yyxx(self) -> Vec4
fn yyxy(self) -> Vec4
fn yyxz(self) -> Vec4
fn yyyx(self) -> Vec4
fn yyyy(self) -> Vec4
fn yyyz(self) -> Vec4
fn yyzx(self) -> Vec4
fn yyzy(self) -> Vec4
fn yyzz(self) -> Vec4
fn yzxx(self) -> Vec4
fn yzxy(self) -> Vec4
fn yzxz(self) -> Vec4
fn yzyx(self) -> Vec4
fn yzyy(self) -> Vec4
fn yzyz(self) -> Vec4
fn yzzx(self) -> Vec4
fn yzzy(self) -> Vec4
fn yzzz(self) -> Vec4
fn zxxx(self) -> Vec4
fn zxxy(self) -> Vec4
fn zxxz(self) -> Vec4
fn zxyx(self) -> Vec4
fn zxyy(self) -> Vec4
fn zxyz(self) -> Vec4
fn zxzx(self) -> Vec4
fn zxzy(self) -> Vec4
fn zxzz(self) -> Vec4
fn zyxx(self) -> Vec4
fn zyxy(self) -> Vec4
fn zyxz(self) -> Vec4
fn zyyx(self) -> Vec4
fn zyyy(self) -> Vec4
fn zyyz(self) -> Vec4
fn zyzx(self) -> Vec4
fn zyzy(self) -> Vec4
fn zyzz(self) -> Vec4
fn zzxx(self) -> Vec4
fn zzxy(self) -> Vec4
fn zzxz(self) -> Vec4
fn zzyx(self) -> Vec4
fn zzyy(self) -> Vec4
fn zzyz(self) -> Vec4
fn zzzx(self) -> Vec4
fn zzzy(self) -> Vec4
fn zzzz(self) -> Vec4
fn xyz(self) -> Self
Source§impl VectorSpace for Vec3
impl VectorSpace for Vec3
Source§impl WriteInto for Vec3
impl WriteInto for Vec3
fn write_into<B>(&self, writer: &mut Writer<B>)where
B: BufferMut,
impl Copy for Vec3
impl Pod for Vec3
impl StructuralPartialEq for Vec3
Auto Trait Implementations§
impl Freeze for Vec3
impl RefUnwindSafe for Vec3
impl Send for Vec3
impl Sync for Vec3
impl Unpin for Vec3
impl UnwindSafe for Vec3
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>
. 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<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<V> Ease for Vwhere
V: VectorSpace,
impl<V> Ease for Vwhere
V: VectorSpace,
Source§fn interpolating_curve_unbounded(start: V, end: V) -> impl Curve<V>
fn interpolating_curve_unbounded(start: V, end: V) -> impl Curve<V>
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<V> StableInterpolate for Vwhere
V: NormedVectorSpace,
impl<V> StableInterpolate for Vwhere
V: NormedVectorSpace,
Source§fn interpolate_stable(&self, other: &V, t: f32) -> V
fn interpolate_stable(&self, other: &V, t: f32) -> V
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<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.