Struct bevy::math::f32::Vec3

source ·
#[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

source

pub const ZERO: Vec3 = _

All zeroes.

source

pub const ONE: Vec3 = _

All ones.

source

pub const NEG_ONE: Vec3 = _

All negative ones.

source

pub const MIN: Vec3 = _

All f32::MIN.

source

pub const MAX: Vec3 = _

All f32::MAX.

source

pub const NAN: Vec3 = _

All f32::NAN.

source

pub const INFINITY: Vec3 = _

All f32::INFINITY.

source

pub const NEG_INFINITY: Vec3 = _

All f32::NEG_INFINITY.

source

pub const X: Vec3 = _

A unit vector pointing along the positive X axis.

source

pub const Y: Vec3 = _

A unit vector pointing along the positive Y axis.

source

pub const Z: Vec3 = _

A unit vector pointing along the positive Z axis.

source

pub const NEG_X: Vec3 = _

A unit vector pointing along the negative X axis.

source

pub const NEG_Y: Vec3 = _

A unit vector pointing along the negative Y axis.

source

pub const NEG_Z: Vec3 = _

A unit vector pointing along the negative Z axis.

source

pub const AXES: [Vec3; 3] = _

The unit axes.

source

pub const fn new(x: f32, y: f32, z: f32) -> Vec3

Creates a new vector.

Examples found in repository?
examples/math/sampling_primitives.rs (line 47)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const DISTANCE_BETWEEN_SHAPES: Vec3 = Vec3::new(2.0, 0.0, 0.0);

/// Maximum amount of points allowed to be present.
/// Should be set such that it does not cause large amounts of lag when reached.
const MAX_POINTS: usize = 3000; // TODO: Test wasm and add a wasm-specific-bound

/// How many points should be spawned each frame
const POINTS_PER_FRAME: usize = 3;

/// Color used for the inside points
const INSIDE_POINT_COLOR: LinearRgba = LinearRgba::rgb(0.855, 1.1, 0.01);
/// Color used for the points on the boundary
const BOUNDARY_POINT_COLOR: LinearRgba = LinearRgba::rgb(0.08, 0.2, 0.90);

/// Time (in seconds) for the spawning/despawning animation
const ANIMATION_TIME: f32 = 1.0;

/// Color for the sky and the sky-light
const SKY_COLOR: Color = Color::srgb(0.02, 0.06, 0.15);

const SMALL_3D: f32 = 0.5;
const BIG_3D: f32 = 1.0;

// primitives

const CUBOID: Cuboid = Cuboid {
    half_size: Vec3::new(SMALL_3D, BIG_3D, SMALL_3D),
};

const SPHERE: Sphere = Sphere {
    radius: 1.5 * SMALL_3D,
};

const TRIANGLE_3D: Triangle3d = Triangle3d {
    vertices: [
        Vec3::new(BIG_3D, -BIG_3D * 0.5, 0.0),
        Vec3::new(0.0, BIG_3D, 0.0),
        Vec3::new(-BIG_3D, -BIG_3D * 0.5, 0.0),
    ],
};

const CAPSULE_3D: Capsule3d = Capsule3d {
    radius: SMALL_3D,
    half_length: SMALL_3D,
};

const CYLINDER: Cylinder = Cylinder {
    radius: SMALL_3D,
    half_height: SMALL_3D,
};

const TETRAHEDRON: Tetrahedron = Tetrahedron {
    vertices: [
        Vec3::new(-BIG_3D, -BIG_3D * 0.67, BIG_3D * 0.5),
        Vec3::new(BIG_3D, -BIG_3D * 0.67, BIG_3D * 0.5),
        Vec3::new(0.0, -BIG_3D * 0.67, -BIG_3D * 1.17),
        Vec3::new(0.0, BIG_3D, 0.0),
    ],
};
More examples
Hide additional examples
examples/games/breakout.rs (line 22)
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
const BALL_STARTING_POSITION: Vec3 = Vec3::new(0.0, -50.0, 1.0);
const BALL_DIAMETER: f32 = 30.;
const BALL_SPEED: f32 = 400.0;
const INITIAL_BALL_DIRECTION: Vec2 = Vec2::new(0.5, -0.5);

const WALL_THICKNESS: f32 = 10.0;
// x coordinates
const LEFT_WALL: f32 = -450.;
const RIGHT_WALL: f32 = 450.;
// y coordinates
const BOTTOM_WALL: f32 = -300.;
const TOP_WALL: f32 = 300.;

const BRICK_SIZE: Vec2 = Vec2::new(100., 30.);
// These values are exact
const GAP_BETWEEN_PADDLE_AND_BRICKS: f32 = 270.0;
const GAP_BETWEEN_BRICKS: f32 = 5.0;
// These values are lower bounds, as the number of bricks is computed
const GAP_BETWEEN_BRICKS_AND_CEILING: f32 = 20.0;
const GAP_BETWEEN_BRICKS_AND_SIDES: f32 = 20.0;

const SCOREBOARD_FONT_SIZE: f32 = 40.0;
const SCOREBOARD_TEXT_PADDING: Val = Val::Px(5.0);

const BACKGROUND_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
const PADDLE_COLOR: Color = Color::srgb(0.3, 0.3, 0.7);
const BALL_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
const BRICK_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
const WALL_COLOR: Color = Color::srgb(0.8, 0.8, 0.8);
const TEXT_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
const SCORE_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(
            stepping::SteppingPlugin::default()
                .add_schedule(Update)
                .add_schedule(FixedUpdate)
                .at(Val::Percent(35.0), Val::Percent(50.0)),
        )
        .insert_resource(Score(0))
        .insert_resource(ClearColor(BACKGROUND_COLOR))
        .add_event::<CollisionEvent>()
        .add_systems(Startup, setup)
        // Add our gameplay simulation systems to the fixed timestep schedule
        // which runs at 64 Hz by default
        .add_systems(
            FixedUpdate,
            (
                apply_velocity,
                move_paddle,
                check_for_collisions,
                play_collision_sound,
            )
                // `chain`ing systems together runs them in order
                .chain(),
        )
        .add_systems(Update, update_scoreboard)
        .run();
}

#[derive(Component)]
struct Paddle;

#[derive(Component)]
struct Ball;

#[derive(Component, Deref, DerefMut)]
struct Velocity(Vec2);

#[derive(Component)]
struct Collider;

#[derive(Event, Default)]
struct CollisionEvent;

#[derive(Component)]
struct Brick;

#[derive(Resource, Deref)]
struct CollisionSound(Handle<AudioSource>);

// This bundle is a collection of the components that define a "wall" in our game
#[derive(Bundle)]
struct WallBundle {
    // You can nest bundles inside of other bundles like this
    // Allowing you to compose their functionality
    sprite_bundle: SpriteBundle,
    collider: Collider,
}

/// Which side of the arena is this wall located on?
enum WallLocation {
    Left,
    Right,
    Bottom,
    Top,
}

impl WallLocation {
    /// Location of the *center* of the wall, used in `transform.translation()`
    fn position(&self) -> Vec2 {
        match self {
            WallLocation::Left => Vec2::new(LEFT_WALL, 0.),
            WallLocation::Right => Vec2::new(RIGHT_WALL, 0.),
            WallLocation::Bottom => Vec2::new(0., BOTTOM_WALL),
            WallLocation::Top => Vec2::new(0., TOP_WALL),
        }
    }

    /// (x, y) dimensions of the wall, used in `transform.scale()`
    fn size(&self) -> Vec2 {
        let arena_height = TOP_WALL - BOTTOM_WALL;
        let arena_width = RIGHT_WALL - LEFT_WALL;
        // Make sure we haven't messed up our constants
        assert!(arena_height > 0.0);
        assert!(arena_width > 0.0);

        match self {
            WallLocation::Left | WallLocation::Right => {
                Vec2::new(WALL_THICKNESS, arena_height + WALL_THICKNESS)
            }
            WallLocation::Bottom | WallLocation::Top => {
                Vec2::new(arena_width + WALL_THICKNESS, WALL_THICKNESS)
            }
        }
    }
}

impl WallBundle {
    // This "builder method" allows us to reuse logic across our wall entities,
    // making our code easier to read and less prone to bugs when we change the logic
    fn new(location: WallLocation) -> WallBundle {
        WallBundle {
            sprite_bundle: SpriteBundle {
                transform: Transform {
                    // We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
                    // This is used to determine the order of our sprites
                    translation: location.position().extend(0.0),
                    // The z-scale of 2D objects must always be 1.0,
                    // or their ordering will be affected in surprising ways.
                    // See https://github.com/bevyengine/bevy/issues/4149
                    scale: location.size().extend(1.0),
                    ..default()
                },
                sprite: Sprite {
                    color: WALL_COLOR,
                    ..default()
                },
                ..default()
            },
            collider: Collider,
        }
    }
}

// This resource tracks the game's score
#[derive(Resource, Deref, DerefMut)]
struct Score(usize);

#[derive(Component)]
struct ScoreboardUi;

// Add the game's entities to our world
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    asset_server: Res<AssetServer>,
) {
    // Camera
    commands.spawn(Camera2dBundle::default());

    // Sound
    let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
    commands.insert_resource(CollisionSound(ball_collision_sound));

    // Paddle
    let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;

    commands.spawn((
        SpriteBundle {
            transform: Transform {
                translation: Vec3::new(0.0, paddle_y, 0.0),
                scale: PADDLE_SIZE.extend(1.0),
                ..default()
            },
            sprite: Sprite {
                color: PADDLE_COLOR,
                ..default()
            },
            ..default()
        },
        Paddle,
        Collider,
    ));

    // Ball
    commands.spawn((
        MaterialMesh2dBundle {
            mesh: meshes.add(Circle::default()).into(),
            material: materials.add(BALL_COLOR),
            transform: Transform::from_translation(BALL_STARTING_POSITION)
                .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
            ..default()
        },
        Ball,
        Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
    ));

    // Scoreboard
    commands.spawn((
        ScoreboardUi,
        TextBundle::from_sections([
            TextSection::new(
                "Score: ",
                TextStyle {
                    font_size: SCOREBOARD_FONT_SIZE,
                    color: TEXT_COLOR,
                    ..default()
                },
            ),
            TextSection::from_style(TextStyle {
                font_size: SCOREBOARD_FONT_SIZE,
                color: SCORE_COLOR,
                ..default()
            }),
        ])
        .with_style(Style {
            position_type: PositionType::Absolute,
            top: SCOREBOARD_TEXT_PADDING,
            left: SCOREBOARD_TEXT_PADDING,
            ..default()
        }),
    ));

    // Walls
    commands.spawn(WallBundle::new(WallLocation::Left));
    commands.spawn(WallBundle::new(WallLocation::Right));
    commands.spawn(WallBundle::new(WallLocation::Bottom));
    commands.spawn(WallBundle::new(WallLocation::Top));

    // Bricks
    let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
    let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
    let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;

    assert!(total_width_of_bricks > 0.0);
    assert!(total_height_of_bricks > 0.0);

    // Given the space available, compute how many rows and columns of bricks we can fit
    let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
    let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
    let n_vertical_gaps = n_columns - 1;

    // Because we need to round the number of columns,
    // the space on the top and sides of the bricks only captures a lower bound, not an exact value
    let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
    let left_edge_of_bricks = center_of_bricks
        // Space taken up by the bricks
        - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
        // Space taken up by the gaps
        - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;

    // In Bevy, the `translation` of an entity describes the center point,
    // not its bottom-left corner
    let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
    let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;

    for row in 0..n_rows {
        for column in 0..n_columns {
            let brick_position = Vec2::new(
                offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
                offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
            );

            // brick
            commands.spawn((
                SpriteBundle {
                    sprite: Sprite {
                        color: BRICK_COLOR,
                        ..default()
                    },
                    transform: Transform {
                        translation: brick_position.extend(0.0),
                        scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
                        ..default()
                    },
                    ..default()
                },
                Brick,
                Collider,
            ));
        }
    }
}
examples/math/render_primitives.rs (line 157)
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
const CUBOID: Cuboid = Cuboid {
    half_size: Vec3::new(BIG_3D, SMALL_3D, BIG_3D),
};

const CIRCLE: Circle = Circle { radius: BIG_2D };
const SPHERE: Sphere = Sphere { radius: BIG_3D };

const ELLIPSE: Ellipse = Ellipse {
    half_size: Vec2::new(BIG_2D, SMALL_2D),
};

const TRIANGLE_2D: Triangle2d = Triangle2d {
    vertices: [
        Vec2::new(BIG_2D, 0.0),
        Vec2::new(0.0, BIG_2D),
        Vec2::new(-BIG_2D, 0.0),
    ],
};

const TRIANGLE_3D: Triangle3d = Triangle3d {
    vertices: [
        Vec3::new(BIG_3D, 0.0, 0.0),
        Vec3::new(0.0, BIG_3D, 0.0),
        Vec3::new(-BIG_3D, 0.0, 0.0),
    ],
};

const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
const PLANE_3D: Plane3d = Plane3d {
    normal: Dir3::Y,
    half_size: Vec2::new(BIG_3D, BIG_3D),
};

const LINE2D: Line2d = Line2d { direction: Dir2::X };
const LINE3D: Line3d = Line3d { direction: Dir3::X };

const SEGMENT_2D: Segment2d = Segment2d {
    direction: Dir2::X,
    half_length: BIG_2D,
};
const SEGMENT_3D: Segment3d = Segment3d {
    direction: Dir3::X,
    half_length: BIG_3D,
};

const POLYLINE_2D: Polyline2d<4> = Polyline2d {
    vertices: [
        Vec2::new(-BIG_2D, -SMALL_2D),
        Vec2::new(-SMALL_2D, SMALL_2D),
        Vec2::new(SMALL_2D, -SMALL_2D),
        Vec2::new(BIG_2D, SMALL_2D),
    ],
};
const POLYLINE_3D: Polyline3d<4> = Polyline3d {
    vertices: [
        Vec3::new(-BIG_3D, -SMALL_3D, -SMALL_3D),
        Vec3::new(SMALL_3D, SMALL_3D, 0.0),
        Vec3::new(-SMALL_3D, -SMALL_3D, 0.0),
        Vec3::new(BIG_3D, SMALL_3D, SMALL_3D),
    ],
};

const POLYGON_2D: Polygon<5> = Polygon {
    vertices: [
        Vec2::new(-BIG_2D, -SMALL_2D),
        Vec2::new(BIG_2D, -SMALL_2D),
        Vec2::new(BIG_2D, SMALL_2D),
        Vec2::new(0.0, 0.0),
        Vec2::new(-BIG_2D, SMALL_2D),
    ],
};

const REGULAR_POLYGON: RegularPolygon = RegularPolygon {
    circumcircle: Circle { radius: BIG_2D },
    sides: 5,
};

const CAPSULE_2D: Capsule2d = Capsule2d {
    radius: SMALL_2D,
    half_length: SMALL_2D,
};
const CAPSULE_3D: Capsule3d = Capsule3d {
    radius: SMALL_3D,
    half_length: SMALL_3D,
};

const CYLINDER: Cylinder = Cylinder {
    radius: SMALL_3D,
    half_height: SMALL_3D,
};

const CONE: Cone = Cone {
    radius: BIG_3D,
    height: BIG_3D,
};

const CONICAL_FRUSTUM: ConicalFrustum = ConicalFrustum {
    radius_top: BIG_3D,
    radius_bottom: SMALL_3D,
    height: BIG_3D,
};

const ANNULUS: Annulus = Annulus {
    inner_circle: Circle { radius: SMALL_2D },
    outer_circle: Circle { radius: BIG_2D },
};

const TORUS: Torus = Torus {
    minor_radius: SMALL_3D / 2.0,
    major_radius: SMALL_3D * 1.5,
};

const TETRAHEDRON: Tetrahedron = Tetrahedron {
    vertices: [
        Vec3::new(-BIG_3D, 0.0, 0.0),
        Vec3::new(BIG_3D, 0.0, 0.0),
        Vec3::new(0.0, 0.0, -BIG_3D * 1.67),
        Vec3::new(0.0, BIG_3D * 1.67, -BIG_3D * 0.5),
    ],
};

const ARC: Arc2d = Arc2d {
    radius: BIG_2D,
    half_angle: std::f32::consts::FRAC_PI_4,
};

const CIRCULAR_SECTOR: CircularSector = CircularSector {
    arc: Arc2d {
        radius: BIG_2D,
        half_angle: std::f32::consts::FRAC_PI_4,
    },
};

const CIRCULAR_SEGMENT: CircularSegment = CircularSegment {
    arc: Arc2d {
        radius: BIG_2D,
        half_angle: std::f32::consts::FRAC_PI_4,
    },
};

fn setup_cameras(mut commands: Commands) {
    let start_in_2d = true;
    let make_camera = |is_active| Camera {
        is_active,
        ..Default::default()
    };

    commands.spawn(Camera2dBundle {
        camera: make_camera(start_in_2d),
        ..Default::default()
    });

    commands.spawn(Camera3dBundle {
        camera: make_camera(!start_in_2d),
        transform: Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
        ..Default::default()
    });
}

fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
    ambient_light.brightness = 50.0;
}

fn setup_lights(mut commands: Commands) {
    commands.spawn(PointLightBundle {
        point_light: PointLight {
            intensity: 5000.0,
            ..default()
        },
        transform: Transform::from_translation(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 2.0, 0.0))
            .looking_at(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0), Vec3::Y),
        ..default()
    });
}

/// Marker component for header text
#[derive(Debug, Clone, Component, Default, Reflect)]
pub struct HeaderText;

/// Marker component for header node
#[derive(Debug, Clone, Component, Default, Reflect)]
pub struct HeaderNode;

fn update_active_cameras(
    state: Res<State<CameraActive>>,
    mut camera_2d: Query<(Entity, &mut Camera), With<Camera2d>>,
    mut camera_3d: Query<(Entity, &mut Camera), (With<Camera3d>, Without<Camera2d>)>,
    mut text: Query<&mut TargetCamera, With<HeaderNode>>,
) {
    let (entity_2d, mut cam_2d) = camera_2d.single_mut();
    let (entity_3d, mut cam_3d) = camera_3d.single_mut();
    let is_camera_2d_active = matches!(*state.get(), CameraActive::Dim2);

    cam_2d.is_active = is_camera_2d_active;
    cam_3d.is_active = !is_camera_2d_active;

    let active_camera = if is_camera_2d_active {
        entity_2d
    } else {
        entity_3d
    };

    text.iter_mut().for_each(|mut target_camera| {
        *target_camera = TargetCamera(active_camera);
    });
}

fn switch_cameras(current: Res<State<CameraActive>>, mut next: ResMut<NextState<CameraActive>>) {
    let next_state = match current.get() {
        CameraActive::Dim2 => CameraActive::Dim3,
        CameraActive::Dim3 => CameraActive::Dim2,
    };
    next.set(next_state);
}

fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
    let active_camera = cameras
        .iter()
        .find_map(|(entity, camera)| camera.is_active.then_some(entity))
        .expect("run condition ensures existence");
    let text = format!("{text}", text = PrimitiveSelected::default());
    let style = TextStyle::default();
    let instructions = "Press 'C' to switch between 2D and 3D mode\n\
        Press 'Up' or 'Down' to switch to the next/previous primitive";
    let text = [
        TextSection::new("Primitive: ", style.clone()),
        TextSection::new(text, style.clone()),
        TextSection::new("\n\n", style.clone()),
        TextSection::new(instructions, style.clone()),
        TextSection::new("\n\n", style.clone()),
        TextSection::new(
            "(If nothing is displayed, there's no rendering support yet)",
            style.clone(),
        ),
    ];

    commands
        .spawn((
            HeaderNode,
            NodeBundle {
                style: Style {
                    justify_self: JustifySelf::Center,
                    top: Val::Px(5.0),
                    ..Default::default()
                },
                ..Default::default()
            },
            TargetCamera(active_camera),
        ))
        .with_children(|parent| {
            parent.spawn((
                HeaderText,
                TextBundle::from_sections(text).with_text_justify(JustifyText::Center),
            ));
        });
}

fn update_text(
    primitive_state: Res<State<PrimitiveSelected>>,
    mut header: Query<&mut Text, With<HeaderText>>,
) {
    let new_text = format!("{text}", text = primitive_state.get());
    header.iter_mut().for_each(|mut header_text| {
        if let Some(kind) = header_text.sections.get_mut(1) {
            kind.value.clone_from(&new_text);
        };
    });
}

fn switch_to_next_primitive(
    current: Res<State<PrimitiveSelected>>,
    mut next: ResMut<NextState<PrimitiveSelected>>,
) {
    let next_state = current.get().next();
    next.set(next_state);
}

fn switch_to_previous_primitive(
    current: Res<State<PrimitiveSelected>>,
    mut next: ResMut<NextState<PrimitiveSelected>>,
) {
    let next_state = current.get().previous();
    next.set(next_state);
}

fn in_mode(active: CameraActive) -> impl Fn(Res<State<CameraActive>>) -> bool {
    move |state| *state.get() == active
}

fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
    const POSITION: Vec2 = Vec2::new(-LEFT_RIGHT_OFFSET_2D, 0.0);
    let angle = time.elapsed_seconds();
    let color = Color::WHITE;

    match state.get() {
        PrimitiveSelected::RectangleAndCuboid => {
            gizmos.primitive_2d(&RECTANGLE, POSITION, angle, color);
        }
        PrimitiveSelected::CircleAndSphere => {
            gizmos.primitive_2d(&CIRCLE, POSITION, angle, color);
        }
        PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, POSITION, angle, color)),
        PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, POSITION, angle, color),
        PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, POSITION, angle, color),
        PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, POSITION, angle, color)),
        PrimitiveSelected::Segment => {
            drop(gizmos.primitive_2d(&SEGMENT_2D, POSITION, angle, color));
        }
        PrimitiveSelected::Polyline => gizmos.primitive_2d(&POLYLINE_2D, POSITION, angle, color),
        PrimitiveSelected::Polygon => gizmos.primitive_2d(&POLYGON_2D, POSITION, angle, color),
        PrimitiveSelected::RegularPolygon => {
            gizmos.primitive_2d(&REGULAR_POLYGON, POSITION, angle, color);
        }
        PrimitiveSelected::Capsule => gizmos.primitive_2d(&CAPSULE_2D, POSITION, angle, color),
        PrimitiveSelected::Cylinder => {}
        PrimitiveSelected::Cone => {}
        PrimitiveSelected::ConicalFrustum => {}
        PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, POSITION, angle, color)),
        PrimitiveSelected::Tetrahedron => {}
        PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, POSITION, angle, color),
        PrimitiveSelected::CircularSector => {
            gizmos.primitive_2d(&CIRCULAR_SECTOR, POSITION, angle, color);
        }
        PrimitiveSelected::CircularSegment => {
            gizmos.primitive_2d(&CIRCULAR_SEGMENT, POSITION, angle, color);
        }
    }
}

/// Marker for primitive meshes to record in which state they should be visible in
#[derive(Debug, Clone, Component, Default, Reflect)]
pub struct PrimitiveData {
    camera_mode: CameraActive,
    primitive_state: PrimitiveSelected,
}

/// Marker for meshes of 2D primitives
#[derive(Debug, Clone, Component, Default)]
pub struct MeshDim2;

/// Marker for meshes of 3D primitives
#[derive(Debug, Clone, Component, Default)]
pub struct MeshDim3;

fn spawn_primitive_2d(
    mut commands: Commands,
    mut materials: ResMut<Assets<ColorMaterial>>,
    mut meshes: ResMut<Assets<Mesh>>,
) {
    const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_2D, 0.0, 0.0);
    let material: Handle<ColorMaterial> = materials.add(Color::WHITE);
    let camera_mode = CameraActive::Dim2;
    [
        Some(RECTANGLE.mesh().build()),
        Some(CIRCLE.mesh().build()),
        Some(ELLIPSE.mesh().build()),
        Some(TRIANGLE_2D.mesh().build()),
        None, // plane
        None, // line
        None, // segment
        None, // polyline
        None, // polygon
        Some(REGULAR_POLYGON.mesh().build()),
        Some(CAPSULE_2D.mesh().build()),
        None, // cylinder
        None, // cone
        None, // conical frustum
        Some(ANNULUS.mesh().build()),
        None, // tetrahedron
    ]
    .into_iter()
    .zip(PrimitiveSelected::ALL)
    .for_each(|(maybe_mesh, state)| {
        if let Some(mesh) = maybe_mesh {
            commands.spawn((
                MeshDim2,
                PrimitiveData {
                    camera_mode,
                    primitive_state: state,
                },
                MaterialMesh2dBundle {
                    mesh: meshes.add(mesh).into(),
                    material: material.clone(),
                    transform: Transform::from_translation(POSITION),
                    ..Default::default()
                },
            ));
        }
    });
}

fn spawn_primitive_3d(
    mut commands: Commands,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut meshes: ResMut<Assets<Mesh>>,
) {
    const POSITION: Vec3 = Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
    let material: Handle<StandardMaterial> = materials.add(Color::WHITE);
    let camera_mode = CameraActive::Dim3;
    [
        Some(CUBOID.mesh().build()),
        Some(SPHERE.mesh().build()),
        None, // ellipse
        Some(TRIANGLE_3D.mesh().build()),
        Some(PLANE_3D.mesh().build()),
        None, // line
        None, // segment
        None, // polyline
        None, // polygon
        None, // regular polygon
        Some(CAPSULE_3D.mesh().build()),
        Some(CYLINDER.mesh().build()),
        None, // cone
        None, // conical frustum
        Some(TORUS.mesh().build()),
        Some(TETRAHEDRON.mesh().build()),
    ]
    .into_iter()
    .zip(PrimitiveSelected::ALL)
    .for_each(|(maybe_mesh, state)| {
        if let Some(mesh) = maybe_mesh {
            commands.spawn((
                MeshDim3,
                PrimitiveData {
                    camera_mode,
                    primitive_state: state,
                },
                PbrBundle {
                    mesh: meshes.add(mesh),
                    material: material.clone(),
                    transform: Transform::from_translation(POSITION),
                    ..Default::default()
                },
            ));
        }
    });
}

fn update_primitive_meshes(
    camera_state: Res<State<CameraActive>>,
    primitive_state: Res<State<PrimitiveSelected>>,
    mut primitives: Query<(&mut Visibility, &PrimitiveData)>,
) {
    primitives.iter_mut().for_each(|(mut vis, primitive)| {
        let visible = primitive.camera_mode == *camera_state.get()
            && primitive.primitive_state == *primitive_state.get();
        *vis = if visible {
            Visibility::Inherited
        } else {
            Visibility::Hidden
        };
    });
}

fn rotate_primitive_2d_meshes(
    mut primitives_2d: Query<
        (&mut Transform, &ViewVisibility),
        (With<PrimitiveData>, With<MeshDim2>),
    >,
    time: Res<Time>,
) {
    let rotation_2d = Quat::from_mat3(&Mat3::from_angle(time.elapsed_seconds()));
    primitives_2d
        .iter_mut()
        .filter(|(_, vis)| vis.get())
        .for_each(|(mut transform, _)| {
            transform.rotation = rotation_2d;
        });
}

fn rotate_primitive_3d_meshes(
    mut primitives_3d: Query<
        (&mut Transform, &ViewVisibility),
        (With<PrimitiveData>, With<MeshDim3>),
    >,
    time: Res<Time>,
) {
    let rotation_3d = Quat::from_rotation_arc(
        Vec3::Z,
        Vec3::new(
            time.elapsed_seconds().sin(),
            time.elapsed_seconds().cos(),
            time.elapsed_seconds().sin() * 0.5,
        )
        .try_normalize()
        .unwrap_or(Vec3::Z),
    );
    primitives_3d
        .iter_mut()
        .filter(|(_, vis)| vis.get())
        .for_each(|(mut transform, _)| {
            transform.rotation = rotation_3d;
        });
}

fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
    const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
    let rotation = Quat::from_rotation_arc(
        Vec3::Z,
        Vec3::new(
            time.elapsed_seconds().sin(),
            time.elapsed_seconds().cos(),
            time.elapsed_seconds().sin() * 0.5,
        )
        .try_normalize()
        .unwrap_or(Vec3::Z),
    );
    let color = Color::WHITE;
    let resolution = 10;

    match state.get() {
        PrimitiveSelected::RectangleAndCuboid => {
            gizmos.primitive_3d(&CUBOID, POSITION, rotation, color);
        }
        PrimitiveSelected::CircleAndSphere => drop(
            gizmos
                .primitive_3d(&SPHERE, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::Ellipse => {}
        PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, POSITION, rotation, color),
        PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, POSITION, rotation, color)),
        PrimitiveSelected::Line => gizmos.primitive_3d(&LINE3D, POSITION, rotation, color),
        PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, POSITION, rotation, color),
        PrimitiveSelected::Polyline => gizmos.primitive_3d(&POLYLINE_3D, POSITION, rotation, color),
        PrimitiveSelected::Polygon => {}
        PrimitiveSelected::RegularPolygon => {}
        PrimitiveSelected::Capsule => drop(
            gizmos
                .primitive_3d(&CAPSULE_3D, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::Cylinder => drop(
            gizmos
                .primitive_3d(&CYLINDER, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::Cone => drop(
            gizmos
                .primitive_3d(&CONE, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::ConicalFrustum => {
            gizmos.primitive_3d(&CONICAL_FRUSTUM, POSITION, rotation, color);
        }

        PrimitiveSelected::Torus => drop(
            gizmos
                .primitive_3d(&TORUS, POSITION, rotation, color)
                .minor_resolution(resolution)
                .major_resolution(resolution),
        ),
        PrimitiveSelected::Tetrahedron => {
            gizmos.primitive_3d(&TETRAHEDRON, POSITION, rotation, color);
        }

        PrimitiveSelected::Arc => {}
        PrimitiveSelected::CircularSector => {}
        PrimitiveSelected::CircularSegment => {}
    }
}
examples/async_tasks/external_source_external_thread.rs (line 75)
69
70
71
72
73
74
75
76
77
78
79
80
fn move_text(
    mut commands: Commands,
    mut texts: Query<(Entity, &mut Transform), With<Text>>,
    time: Res<Time>,
) {
    for (entity, mut position) in &mut texts {
        position.translation -= Vec3::new(0.0, 100.0 * time.delta_seconds(), 0.0);
        if position.translation.y < -300.0 {
            commands.entity(entity).despawn();
        }
    }
}
examples/animation/gltf_skinned_mesh.rs (line 24)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // Create a camera
    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(-2.0, 2.5, 5.0)
            .looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y),
        ..default()
    });

    // Spawn the first scene in `models/SimpleSkin/SimpleSkin.gltf`
    commands.spawn(SceneBundle {
        scene: asset_server
            .load(GltfAssetLabel::Scene(0).from_asset("models/SimpleSkin/SimpleSkin.gltf")),
        ..default()
    });
}
examples/async_tasks/async_compute.rs (line 140)
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
fn setup_env(mut commands: Commands) {
    // Used to center camera on spawned cubes
    let offset = if NUM_CUBES % 2 == 0 {
        (NUM_CUBES / 2) as f32 - 0.5
    } else {
        (NUM_CUBES / 2) as f32
    };

    // lights
    commands.spawn(PointLightBundle {
        transform: Transform::from_xyz(4.0, 12.0, 15.0),
        ..default()
    });

    // camera
    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(offset, offset, 15.0)
            .looking_at(Vec3::new(offset, offset, 0.0), Vec3::Y),
        ..default()
    });
}
source

pub const fn splat(v: f32) -> Vec3

Creates a vector with all elements set to v.

Examples found in repository?
examples/3d/irradiance_volumes.rs (line 276)
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
fn spawn_sphere(commands: &mut Commands, assets: &ExampleAssets) {
    commands
        .spawn(PbrBundle {
            mesh: assets.main_sphere.clone(),
            material: assets.main_sphere_material.clone(),
            transform: Transform::from_xyz(0.0, SPHERE_SCALE, 0.0)
                .with_scale(Vec3::splat(SPHERE_SCALE)),
            ..default()
        })
        .insert(MainObject);
}

fn spawn_voxel_cube_parent(commands: &mut Commands) {
    commands
        .spawn(SpatialBundle {
            visibility: Visibility::Hidden,
            ..default()
        })
        .insert(VoxelCubeParent);
}

fn spawn_fox(commands: &mut Commands, assets: &ExampleAssets) {
    commands
        .spawn(SceneBundle {
            scene: assets.fox.clone(),
            visibility: Visibility::Hidden,
            transform: Transform::from_scale(Vec3::splat(FOX_SCALE)),
            ..default()
        })
        .insert(MainObject);
}

fn spawn_text(commands: &mut Commands, app_status: &AppStatus) {
    commands.spawn(
        TextBundle {
            text: app_status.create_text(),
            ..default()
        }
        .with_style(Style {
            position_type: PositionType::Absolute,
            bottom: Val::Px(12.0),
            left: Val::Px(12.0),
            ..default()
        }),
    );
}

// A system that updates the help text.
fn update_text(mut text_query: Query<&mut Text>, app_status: Res<AppStatus>) {
    for mut text in text_query.iter_mut() {
        *text = app_status.create_text();
    }
}

impl AppStatus {
    // Constructs the help text at the bottom of the screen based on the
    // application status.
    fn create_text(&self) -> Text {
        let irradiance_volume_help_text = if self.irradiance_volume_present {
            DISABLE_IRRADIANCE_VOLUME_HELP_TEXT
        } else {
            ENABLE_IRRADIANCE_VOLUME_HELP_TEXT
        };

        let voxels_help_text = if self.voxels_visible {
            HIDE_VOXELS_HELP_TEXT
        } else {
            SHOW_VOXELS_HELP_TEXT
        };

        let rotation_help_text = if self.rotating {
            STOP_ROTATION_HELP_TEXT
        } else {
            START_ROTATION_HELP_TEXT
        };

        let switch_mesh_help_text = match self.model {
            ExampleModel::Sphere => SWITCH_TO_FOX_HELP_TEXT,
            ExampleModel::Fox => SWITCH_TO_SPHERE_HELP_TEXT,
        };

        Text::from_section(
            format!(
                "{}\n{}\n{}\n{}\n{}",
                CLICK_TO_MOVE_HELP_TEXT,
                voxels_help_text,
                irradiance_volume_help_text,
                rotation_help_text,
                switch_mesh_help_text
            ),
            TextStyle::default(),
        )
    }
}

// Rotates the camera a bit every frame.
fn rotate_camera(
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    time: Res<Time>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_seconds())
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}

// Toggles between the unskinned sphere model and the skinned fox model if the
// user requests it.
fn change_main_object(
    keyboard: Res<ButtonInput<KeyCode>>,
    mut app_status: ResMut<AppStatus>,
    mut sphere_query: Query<
        &mut Visibility,
        (With<MainObject>, With<Handle<Mesh>>, Without<Handle<Scene>>),
    >,
    mut fox_query: Query<&mut Visibility, (With<MainObject>, With<Handle<Scene>>)>,
) {
    if !keyboard.just_pressed(KeyCode::Tab) {
        return;
    }
    let Some(mut sphere_visibility) = sphere_query.iter_mut().next() else {
        return;
    };
    let Some(mut fox_visibility) = fox_query.iter_mut().next() else {
        return;
    };

    match app_status.model {
        ExampleModel::Sphere => {
            *sphere_visibility = Visibility::Hidden;
            *fox_visibility = Visibility::Visible;
            app_status.model = ExampleModel::Fox;
        }
        ExampleModel::Fox => {
            *sphere_visibility = Visibility::Visible;
            *fox_visibility = Visibility::Hidden;
            app_status.model = ExampleModel::Sphere;
        }
    }
}

impl Default for AppStatus {
    fn default() -> Self {
        Self {
            irradiance_volume_present: true,
            rotating: true,
            model: ExampleModel::Sphere,
            voxels_visible: false,
        }
    }
}

// Turns on and off the irradiance volume as requested by the user.
fn toggle_irradiance_volumes(
    mut commands: Commands,
    keyboard: Res<ButtonInput<KeyCode>>,
    light_probe_query: Query<Entity, With<LightProbe>>,
    mut app_status: ResMut<AppStatus>,
    assets: Res<ExampleAssets>,
    mut ambient_light: ResMut<AmbientLight>,
) {
    if !keyboard.just_pressed(KeyCode::Space) {
        return;
    };

    let Some(light_probe) = light_probe_query.iter().next() else {
        return;
    };

    if app_status.irradiance_volume_present {
        commands.entity(light_probe).remove::<IrradianceVolume>();
        ambient_light.brightness = AMBIENT_LIGHT_BRIGHTNESS * IRRADIANCE_VOLUME_INTENSITY;
        app_status.irradiance_volume_present = false;
    } else {
        commands.entity(light_probe).insert(IrradianceVolume {
            voxels: assets.irradiance_volume.clone(),
            intensity: IRRADIANCE_VOLUME_INTENSITY,
        });
        ambient_light.brightness = 0.0;
        app_status.irradiance_volume_present = true;
    }
}

fn toggle_rotation(keyboard: Res<ButtonInput<KeyCode>>, mut app_status: ResMut<AppStatus>) {
    if keyboard.just_pressed(KeyCode::Enter) {
        app_status.rotating = !app_status.rotating;
    }
}

// Handles clicks on the plane that reposition the object.
fn handle_mouse_clicks(
    buttons: Res<ButtonInput<MouseButton>>,
    windows: Query<&Window, With<PrimaryWindow>>,
    cameras: Query<(&Camera, &GlobalTransform)>,
    mut main_objects: Query<&mut Transform, With<MainObject>>,
) {
    if !buttons.pressed(MouseButton::Left) {
        return;
    }
    let Some(mouse_position) = windows
        .iter()
        .next()
        .and_then(|window| window.cursor_position())
    else {
        return;
    };
    let Some((camera, camera_transform)) = cameras.iter().next() else {
        return;
    };

    // Figure out where the user clicked on the plane.
    let Some(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
        return;
    };
    let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else {
        return;
    };
    let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;

    // Move all the main objeccts.
    for mut transform in main_objects.iter_mut() {
        transform.translation = vec3(
            plane_intersection.x,
            transform.translation.y,
            plane_intersection.z,
        );
    }
}

impl FromWorld for ExampleAssets {
    fn from_world(world: &mut World) -> Self {
        let fox_animation =
            world.load_asset(GltfAssetLabel::Animation(1).from_asset("models/animated/Fox.glb"));
        let (fox_animation_graph, fox_animation_node) =
            AnimationGraph::from_clip(fox_animation.clone());

        ExampleAssets {
            main_sphere: world.add_asset(Sphere::default().mesh().uv(32, 18)),
            fox: world.load_asset(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")),
            main_sphere_material: world.add_asset(Color::from(SILVER)),
            main_scene: world.load_asset(
                GltfAssetLabel::Scene(0)
                    .from_asset("models/IrradianceVolumeExample/IrradianceVolumeExample.glb"),
            ),
            irradiance_volume: world.load_asset("irradiance_volumes/Example.vxgi.ktx2"),
            fox_animation_graph: world.add_asset(fox_animation_graph),
            fox_animation_node,
            voxel_cube: world.add_asset(Cuboid::default()),
            // Just use a specular map for the skybox since it's not too blurry.
            // In reality you wouldn't do this--you'd use a real skybox texture--but
            // reusing the textures like this saves space in the Bevy repository.
            skybox: world.load_asset("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
        }
    }
}

// Plays the animation on the fox.
fn play_animations(
    mut commands: Commands,
    assets: Res<ExampleAssets>,
    mut players: Query<(Entity, &mut AnimationPlayer), Without<Handle<AnimationGraph>>>,
) {
    for (entity, mut player) in players.iter_mut() {
        commands
            .entity(entity)
            .insert(assets.fox_animation_graph.clone());
        player.play(assets.fox_animation_node).repeat();
    }
}

fn create_cubes(
    image_assets: Res<Assets<Image>>,
    mut commands: Commands,
    irradiance_volumes: Query<(&IrradianceVolume, &GlobalTransform)>,
    voxel_cube_parents: Query<Entity, With<VoxelCubeParent>>,
    voxel_cubes: Query<Entity, With<VoxelCube>>,
    example_assets: Res<ExampleAssets>,
    mut voxel_visualization_material_assets: ResMut<Assets<VoxelVisualizationMaterial>>,
) {
    // If voxel cubes have already been spawned, don't do anything.
    if !voxel_cubes.is_empty() {
        return;
    }

    let Some(voxel_cube_parent) = voxel_cube_parents.iter().next() else {
        return;
    };

    for (irradiance_volume, global_transform) in irradiance_volumes.iter() {
        let Some(image) = image_assets.get(&irradiance_volume.voxels) else {
            continue;
        };

        let resolution = image.texture_descriptor.size;

        let voxel_cube_material = voxel_visualization_material_assets.add(ExtendedMaterial {
            base: StandardMaterial::from(Color::from(RED)),
            extension: VoxelVisualizationExtension {
                irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo {
                    world_from_voxel: VOXEL_FROM_WORLD.inverse(),
                    voxel_from_world: VOXEL_FROM_WORLD,
                    resolution: uvec3(
                        resolution.width,
                        resolution.height,
                        resolution.depth_or_array_layers,
                    ),
                    intensity: IRRADIANCE_VOLUME_INTENSITY,
                },
            },
        });

        let scale = vec3(
            1.0 / resolution.width as f32,
            1.0 / resolution.height as f32,
            1.0 / resolution.depth_or_array_layers as f32,
        );

        // Spawn a cube for each voxel.
        for z in 0..resolution.depth_or_array_layers {
            for y in 0..resolution.height {
                for x in 0..resolution.width {
                    let uvw = (uvec3(x, y, z).as_vec3() + 0.5) * scale - 0.5;
                    let pos = global_transform.transform_point(uvw);
                    let voxel_cube = commands
                        .spawn(MaterialMeshBundle {
                            mesh: example_assets.voxel_cube.clone(),
                            material: voxel_cube_material.clone(),
                            transform: Transform::from_scale(Vec3::splat(VOXEL_CUBE_SCALE))
                                .with_translation(pos),
                            ..default()
                        })
                        .insert(VoxelCube)
                        .insert(NotShadowCaster)
                        .id();

                    commands.entity(voxel_cube_parent).add_child(voxel_cube);
                }
            }
        }
    }
}
More examples
Hide additional examples
examples/games/alien_cake_addict.rs (line 380)
375
376
377
378
379
380
381
382
383
fn rotate_bonus(game: Res<Game>, time: Res<Time>, mut transforms: Query<&mut Transform>) {
    if let Some(entity) = game.bonus.entity {
        if let Ok(mut cake_transform) = transforms.get_mut(entity) {
            cake_transform.rotate_y(time.delta_seconds());
            cake_transform.scale =
                Vec3::splat(1.0 + (game.score as f32 / 10.0 * time.elapsed_seconds().sin()).abs());
        }
    }
}
examples/3d/ssr.rs (line 172)
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
fn spawn_flight_helmet(commands: &mut Commands, asset_server: &AssetServer) {
    commands
        .spawn(SceneBundle {
            scene: asset_server
                .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")),
            transform: Transform::from_scale(Vec3::splat(2.5)),
            ..default()
        })
        .insert(FlightHelmetModel)
        .insert(Visibility::Hidden);
}

// Spawns the water plane.
fn spawn_water(
    commands: &mut Commands,
    asset_server: &AssetServer,
    meshes: &mut Assets<Mesh>,
    water_materials: &mut Assets<ExtendedMaterial<StandardMaterial, Water>>,
) {
    commands.spawn(MaterialMeshBundle {
        mesh: meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0))),
        material: water_materials.add(ExtendedMaterial {
            base: StandardMaterial {
                base_color: BLACK.into(),
                perceptual_roughness: 0.0,
                ..default()
            },
            extension: Water {
                normals: asset_server.load_with_settings::<Image, ImageLoaderSettings>(
                    "textures/water_normals.png",
                    |settings| {
                        settings.is_srgb = false;
                        settings.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor {
                            address_mode_u: ImageAddressMode::Repeat,
                            address_mode_v: ImageAddressMode::Repeat,
                            mag_filter: ImageFilterMode::Linear,
                            min_filter: ImageFilterMode::Linear,
                            ..default()
                        });
                    },
                ),
                // These water settings are just random values to create some
                // variety.
                settings: WaterSettings {
                    octave_vectors: [
                        vec4(0.080, 0.059, 0.073, -0.062),
                        vec4(0.153, 0.138, -0.149, -0.195),
                    ],
                    octave_scales: vec4(1.0, 2.1, 7.9, 14.9) * 5.0,
                    octave_strengths: vec4(0.16, 0.18, 0.093, 0.044),
                },
            },
        }),
        transform: Transform::from_scale(Vec3::splat(100.0)),
        ..default()
    });
}
examples/2d/mesh2d.rs (line 20)
12
13
14
15
16
17
18
19
20
21
22
23
24
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn(MaterialMesh2dBundle {
        mesh: meshes.add(Rectangle::default()).into(),
        transform: Transform::default().with_scale(Vec3::splat(128.)),
        material: materials.add(Color::from(PURPLE)),
        ..default()
    });
}
examples/2d/pixel_grid_snap.rs (line 87)
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
fn setup_mesh(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn((
        MaterialMesh2dBundle {
            mesh: meshes.add(Capsule2d::default()).into(),
            transform: Transform::from_xyz(40., 0., 2.).with_scale(Vec3::splat(32.)),
            material: materials.add(Color::BLACK),
            ..default()
        },
        Rotate,
        PIXEL_PERFECT_LAYERS,
    ));
}
examples/math/sampling_primitives.rs (line 662)
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
fn animate_spawning(
    mut commands: Commands,
    time: Res<Time>,
    mut samples: Query<(Entity, &mut Transform, &mut SpawningPoint)>,
) {
    let dt = time.delta_seconds();

    for (entity, mut transform, mut point) in samples.iter_mut() {
        point.progress += dt / ANIMATION_TIME;
        transform.scale = Vec3::splat(point.progress.min(1.0));
        if point.progress >= 1.0 {
            commands.entity(entity).remove::<SpawningPoint>();
        }
    }
}

fn animate_despawning(
    mut commands: Commands,
    time: Res<Time>,
    mut samples: Query<(Entity, &mut Transform, &mut DespawningPoint)>,
) {
    let dt = time.delta_seconds();

    for (entity, mut transform, mut point) in samples.iter_mut() {
        point.progress += dt / ANIMATION_TIME;
        // If the point is already smaller than expected, jump ahead with the despawning progress to avoid sudden jumps in size
        point.progress = f32::max(point.progress, 1.0 - transform.scale.x);
        transform.scale = Vec3::splat((1.0 - point.progress).max(0.0));
        if point.progress >= 1.0 {
            commands.entity(entity).despawn();
        }
    }
}
source

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.

source

pub const fn from_array(a: [f32; 3]) -> Vec3

Creates a new vector from an array.

source

pub const fn to_array(&self) -> [f32; 3]

[x, y, z]

source

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.

source

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.

source

pub fn extend(self, w: f32) -> Vec4

Creates a 4D vector from self and the given w value.

source

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?
examples/ecs/observers.rs (line 187)
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
fn handle_click(
    mouse_button_input: Res<ButtonInput<MouseButton>>,
    camera: Query<(&Camera, &GlobalTransform)>,
    windows: Query<&Window>,
    mut commands: Commands,
) {
    let (camera, camera_transform) = camera.single();
    if let Some(pos) = windows
        .single()
        .cursor_position()
        .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor))
        .map(|ray| ray.origin.truncate())
    {
        if mouse_button_input.just_pressed(MouseButton::Left) {
            commands.trigger(ExplodeMines { pos, radius: 1.0 });
        }
    }
}
More examples
Hide additional examples
examples/2d/mesh2d_arcs.rs (line 115)
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
fn draw_bounds<Shape: Bounded2d + Send + Sync + 'static>(
    q: Query<(&DrawBounds<Shape>, &GlobalTransform)>,
    mut gizmos: Gizmos,
) {
    for (shape, transform) in &q {
        let (_, rotation, translation) = transform.to_scale_rotation_translation();
        let translation = translation.truncate();
        let rotation = rotation.to_euler(EulerRot::XYZ).2;

        let aabb = shape.0.aabb_2d(translation, rotation);
        gizmos.rect_2d(aabb.center(), 0.0, aabb.half_size() * 2.0, RED);

        let bounding_circle = shape.0.bounding_circle(translation, rotation);
        gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE);
    }
}
examples/games/desk_toy.rs (line 253)
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
fn update_cursor_hit_test(
    cursor_world_pos: Res<CursorWorldPos>,
    mut q_primary_window: Query<&mut Window, With<PrimaryWindow>>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    let mut primary_window = q_primary_window.single_mut();

    // If the window has decorations (e.g. a border) then it should be clickable
    if primary_window.decorations {
        primary_window.cursor.hit_test = true;
        return;
    }

    // If the cursor is not within the window we don't need to update whether the window is clickable or not
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // If the cursor is within the radius of the Bevy logo make the window clickable otherwise the window is not clickable
    let bevy_logo_transform = q_bevy_logo.single();
    primary_window.cursor.hit_test = bevy_logo_transform
        .translation
        .truncate()
        .distance(cursor_world_pos)
        < BEVY_LOGO_RADIUS;
}

/// Start the drag operation and record the offset we started dragging from
fn start_drag(
    mut commands: Commands,
    cursor_world_pos: Res<CursorWorldPos>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // Get the offset from the cursor to the Bevy logo sprite
    let bevy_logo_transform = q_bevy_logo.single();
    let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;

    // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
    if drag_offset.length() < BEVY_LOGO_RADIUS {
        commands.insert_resource(DragOperation(drag_offset));
    }
}

/// Stop the current drag operation
fn end_drag(mut commands: Commands) {
    commands.remove_resource::<DragOperation>();
}

/// Drag the Bevy logo
fn drag(
    drag_offset: Res<DragOperation>,
    cursor_world_pos: Res<CursorWorldPos>,
    time: Res<Time>,
    mut q_bevy_logo: Query<&mut Transform, With<BevyLogo>>,
    mut q_pupils: Query<&mut Pupil>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // Get the current Bevy logo transform
    let mut bevy_transform = q_bevy_logo.single_mut();

    // Calculate the new translation of the Bevy logo based on cursor and drag offset
    let new_translation = cursor_world_pos + drag_offset.0;

    // Calculate how fast we are dragging the Bevy logo (unit/second)
    let drag_velocity =
        (new_translation - bevy_transform.translation.truncate()) / time.delta_seconds();

    // Update the translation of Bevy logo transform to new translation
    bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);

    // Add the cursor drag velocity in the opposite direction to each pupil.
    // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
    // simulate inertia, otherwise they will move fixed to the parent.
    for mut pupil in &mut q_pupils {
        pupil.velocity -= drag_velocity;
    }
}

/// Quit when the user right clicks the Bevy logo
fn quit(
    cursor_world_pos: Res<CursorWorldPos>,
    mut app_exit: EventWriter<AppExit>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
    let bevy_logo_transform = q_bevy_logo.single();
    if bevy_logo_transform
        .translation
        .truncate()
        .distance(cursor_world_pos)
        < BEVY_LOGO_RADIUS
    {
        app_exit.send(AppExit::Success);
    }
}

/// Enable transparency for the window and make it on top
fn toggle_transparency(
    mut commands: Commands,
    mut window_transparency: ResMut<WindowTransparency>,
    mut q_instructions_text: Query<&mut Visibility, With<InstructionsText>>,
    mut q_primary_window: Query<&mut Window, With<PrimaryWindow>>,
) {
    // Toggle the window transparency resource
    window_transparency.0 = !window_transparency.0;

    // Show or hide the instructions text
    for mut visibility in &mut q_instructions_text {
        *visibility = if window_transparency.0 {
            Visibility::Hidden
        } else {
            Visibility::Visible
        };
    }

    // 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
    // only if window transparency is enabled
    let mut window = q_primary_window.single_mut();
    let clear_color;
    (window.decorations, window.window_level, clear_color) = if window_transparency.0 {
        (false, WindowLevel::AlwaysOnTop, Color::NONE)
    } else {
        (true, WindowLevel::Normal, WINDOW_CLEAR_COLOR)
    };

    // Set the clear color
    commands.insert_resource(ClearColor(clear_color));
}

/// Move the pupils and bounce them around
fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
    for (mut pupil, mut transform) in &mut q_pupils {
        // The wiggle radius is how much the pupil can move within the eye
        let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
        // Store the Z component
        let z = transform.translation.z;
        // Truncate the Z component to make the calculations be on [`Vec2`]
        let mut translation = transform.translation.truncate();
        // Decay the pupil velocity
        pupil.velocity *= (0.04f32).powf(time.delta_seconds());
        // Move the pupil
        translation += pupil.velocity * time.delta_seconds();
        // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
        // This is not physically accurate but it's good enough for the googly eyes effect.
        if translation.length() > wiggle_radius {
            translation = translation.normalize() * wiggle_radius;
            // Invert and decrease the velocity of the pupil when it bounces
            pupil.velocity *= -0.75;
        }
        // Update the entity transform with the new translation after reading the Z component
        transform.translation = translation.extend(z);
    }
}
examples/games/breakout.rs (line 371)
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
fn check_for_collisions(
    mut commands: Commands,
    mut score: ResMut<Score>,
    mut ball_query: Query<(&mut Velocity, &Transform), With<Ball>>,
    collider_query: Query<(Entity, &Transform, Option<&Brick>), With<Collider>>,
    mut collision_events: EventWriter<CollisionEvent>,
) {
    let (mut ball_velocity, ball_transform) = ball_query.single_mut();

    for (collider_entity, collider_transform, maybe_brick) in &collider_query {
        let collision = ball_collision(
            BoundingCircle::new(ball_transform.translation.truncate(), BALL_DIAMETER / 2.),
            Aabb2d::new(
                collider_transform.translation.truncate(),
                collider_transform.scale.truncate() / 2.,
            ),
        );

        if let Some(collision) = collision {
            // Sends a collision event so that other systems can react to the collision
            collision_events.send_default();

            // Bricks should be despawned and increment the scoreboard on collision
            if maybe_brick.is_some() {
                commands.entity(collider_entity).despawn();
                **score += 1;
            }

            // Reflect the ball's velocity when it collides
            let mut reflect_x = false;
            let mut reflect_y = false;

            // Reflect only if the velocity is in the opposite direction of the collision
            // This prevents the ball from getting stuck inside the bar
            match collision {
                Collision::Left => reflect_x = ball_velocity.x > 0.0,
                Collision::Right => reflect_x = ball_velocity.x < 0.0,
                Collision::Top => reflect_y = ball_velocity.y < 0.0,
                Collision::Bottom => reflect_y = ball_velocity.y > 0.0,
            }

            // Reflect velocity on the x-axis if we hit something on the x-axis
            if reflect_x {
                ball_velocity.x = -ball_velocity.x;
            }

            // Reflect velocity on the y-axis if we hit something on the y-axis
            if reflect_y {
                ball_velocity.y = -ball_velocity.y;
            }
        }
    }
}
source

pub fn with_x(self, x: f32) -> Vec3

Creates a 3D vector from self with the given value of x.

source

pub fn with_y(self, y: f32) -> Vec3

Creates a 3D vector from self with the given value of y.

source

pub fn with_z(self, z: f32) -> Vec3

Creates a 3D vector from self with the given value of z.

source

pub fn dot(self, rhs: Vec3) -> f32

Computes the dot product of self and rhs.

source

pub fn dot_into_vec(self, rhs: Vec3) -> Vec3

Returns a vector where every component is the dot product of self and rhs.

source

pub fn cross(self, rhs: Vec3) -> Vec3

Computes the cross product of self and rhs.

source

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?
examples/2d/rotation.rs (line 155)
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
fn player_movement_system(
    time: Res<Time>,
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut query: Query<(&Player, &mut Transform)>,
) {
    let (ship, mut transform) = query.single_mut();

    let mut rotation_factor = 0.0;
    let mut movement_factor = 0.0;

    if keyboard_input.pressed(KeyCode::ArrowLeft) {
        rotation_factor += 1.0;
    }

    if keyboard_input.pressed(KeyCode::ArrowRight) {
        rotation_factor -= 1.0;
    }

    if keyboard_input.pressed(KeyCode::ArrowUp) {
        movement_factor += 1.0;
    }

    // update the ship rotation around the Z axis (perpendicular to the 2D plane of the screen)
    transform.rotate_z(rotation_factor * ship.rotation_speed * time.delta_seconds());

    // get the ship's forward vector by applying the current rotation to the ships initial facing
    // vector
    let movement_direction = transform.rotation * Vec3::Y;
    // get the distance the ship will move based on direction, the ship's movement speed and delta
    // time
    let movement_distance = movement_factor * ship.movement_speed * time.delta_seconds();
    // create the change in translation using the new movement direction and distance
    let translation_delta = movement_direction * movement_distance;
    // update the ship translation with our new translation delta
    transform.translation += translation_delta;

    // bound the ship within the invisible level bounds
    let extents = Vec3::from((BOUNDS / 2.0, 0.0));
    transform.translation = transform.translation.min(extents).max(-extents);
}
source

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?
examples/2d/rotation.rs (line 155)
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
fn player_movement_system(
    time: Res<Time>,
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut query: Query<(&Player, &mut Transform)>,
) {
    let (ship, mut transform) = query.single_mut();

    let mut rotation_factor = 0.0;
    let mut movement_factor = 0.0;

    if keyboard_input.pressed(KeyCode::ArrowLeft) {
        rotation_factor += 1.0;
    }

    if keyboard_input.pressed(KeyCode::ArrowRight) {
        rotation_factor -= 1.0;
    }

    if keyboard_input.pressed(KeyCode::ArrowUp) {
        movement_factor += 1.0;
    }

    // update the ship rotation around the Z axis (perpendicular to the 2D plane of the screen)
    transform.rotate_z(rotation_factor * ship.rotation_speed * time.delta_seconds());

    // get the ship's forward vector by applying the current rotation to the ships initial facing
    // vector
    let movement_direction = transform.rotation * Vec3::Y;
    // get the distance the ship will move based on direction, the ship's movement speed and delta
    // time
    let movement_distance = movement_factor * ship.movement_speed * time.delta_seconds();
    // create the change in translation using the new movement direction and distance
    let translation_delta = movement_direction * movement_distance;
    // update the ship translation with our new translation delta
    transform.translation += translation_delta;

    // bound the ship within the invisible level bounds
    let extents = Vec3::from((BOUNDS / 2.0, 0.0));
    transform.translation = transform.translation.min(extents).max(-extents);
}
source

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.

source

pub fn min_element(self) -> f32

Returns the horizontal minimum of self.

In other words this computes min(x, y, ..).

Examples found in repository?
examples/transforms/scale.rs (line 84)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
    for (mut transform, mut cube) in &mut cubes {
        // If an entity scaled beyond the maximum of its size in any dimension
        // the scaling vector is flipped so the scaling is gradually reverted.
        // Additionally, to ensure the condition does not trigger again we floor the elements to
        // their next full value, which should be max_element_size at max.
        if transform.scale.max_element() > cube.max_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.floor();
        }
        // If an entity scaled beyond the minimum of its size in any dimension
        // the scaling vector is also flipped.
        // Additionally the Values are ceiled to be min_element_size at least
        // and the scale direction is flipped.
        // This way the entity will change the dimension in which it is scaled any time it
        // reaches its min_element_size.
        if transform.scale.min_element() < cube.min_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.ceil();
            cube.scale_direction = cube.scale_direction.zxy();
        }
    }
}
source

pub fn max_element(self) -> f32

Returns the horizontal maximum of self.

In other words this computes max(x, y, ..).

Examples found in repository?
examples/transforms/scale.rs (line 74)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
    for (mut transform, mut cube) in &mut cubes {
        // If an entity scaled beyond the maximum of its size in any dimension
        // the scaling vector is flipped so the scaling is gradually reverted.
        // Additionally, to ensure the condition does not trigger again we floor the elements to
        // their next full value, which should be max_element_size at max.
        if transform.scale.max_element() > cube.max_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.floor();
        }
        // If an entity scaled beyond the minimum of its size in any dimension
        // the scaling vector is also flipped.
        // Additionally the Values are ceiled to be min_element_size at least
        // and the scale direction is flipped.
        // This way the entity will change the dimension in which it is scaled any time it
        // reaches its min_element_size.
        if transform.scale.min_element() < cube.min_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.ceil();
            cube.scale_direction = cube.scale_direction.zxy();
        }
    }
}
source

pub fn element_sum(self) -> f32

Returns the sum of all elements of self.

In other words, this computes self.x + self.y + ...

source

pub fn element_product(self) -> f32

Returns the product of all elements of self.

In other words, this computes self.x * self.y * ...

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

pub fn abs(self) -> Vec3

Returns a vector containing the absolute value of each element of self.

source

pub fn signum(self) -> Vec3

Returns a vector with elements representing the sign of self.

  • 1.0 if the number is positive, +0.0 or INFINITY
  • -1.0 if the number is negative, -0.0 or NEG_INFINITY
  • NAN if the number is NAN
source

pub fn copysign(self, rhs: Vec3) -> Vec3

Returns a vector with signs of rhs and the magnitudes of self.

source

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.

source

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.

source

pub fn is_nan(self) -> bool

Returns true if any elements are NaN.

source

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(), z.is_nan(), w.is_nan()].

source

pub fn length(self) -> f32

Computes the length of self.

Examples found in repository?
examples/transforms/translation.rs (line 68)
65
66
67
68
69
70
71
72
73
74
fn move_cube(mut cubes: Query<(&mut Transform, &mut Movable)>, timer: Res<Time>) {
    for (mut transform, mut cube) in &mut cubes {
        // Check if the entity moved too far from its spawn, if so invert the moving direction.
        if (cube.spawn - transform.translation).length() > cube.max_distance {
            cube.speed *= -1.0;
        }
        let direction = transform.local_x();
        transform.translation += direction * cube.speed * timer.delta_seconds();
    }
}
More examples
Hide additional examples
examples/3d/motion_blur.rs (line 341)
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
fn move_cars(
    time: Res<Time>,
    mut movables: Query<(&mut Transform, &Moves, &Children)>,
    mut spins: Query<&mut Transform, (Without<Moves>, With<Rotates>)>,
) {
    for (mut transform, moves, children) in &mut movables {
        let time = time.elapsed_seconds() * 0.25;
        let t = time + 0.5 * moves.0;
        let dx = t.cos();
        let dz = -(3.0 * t).sin();
        let speed_variation = (dx * dx + dz * dz).sqrt() * 0.15;
        let t = t + speed_variation;
        let prev = transform.translation;
        transform.translation.x = race_track_pos(0.0, t).x;
        transform.translation.z = race_track_pos(0.0, t).y;
        transform.translation.y = -0.59;
        let delta = transform.translation - prev;
        transform.look_to(delta, Vec3::Y);
        for child in children.iter() {
            let Ok(mut wheel) = spins.get_mut(*child) else {
                continue;
            };
            let radius = wheel.scale.x;
            let circumference = 2.0 * std::f32::consts::PI * radius;
            let angle = delta.length() / circumference * std::f32::consts::PI * 2.0;
            wheel.rotate_local_y(angle);
        }
    }
}
examples/transforms/transform.rs (line 140)
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
fn scale_down_sphere_proportional_to_cube_travel_distance(
    cubes: Query<(&Transform, &CubeState), Without<Center>>,
    mut centers: Query<(&mut Transform, &Center)>,
) {
    // First we need to calculate the length of between
    // the current position of the orbiting cube and the spawn position.
    let mut distances = 0.0;
    for (cube_transform, cube_state) in &cubes {
        distances += (cube_state.start_pos - cube_transform.translation).length();
    }
    // Now we use the calculated value to scale the sphere in the center accordingly.
    for (mut transform, center) in &mut centers {
        // Calculate the new size from the calculated distances and the centers scale_factor.
        // Since we want to have the sphere at its max_size at the cubes spawn location we start by
        // using the max_size as start value and subtract the distances scaled by a scaling factor.
        let mut new_size: f32 = center.max_size - center.scale_factor * distances;

        // The new size should also not be smaller than the centers min_size.
        // Therefore the max value out of (new_size, center.min_size) is used.
        new_size = new_size.max(center.min_size);

        // Now scale the sphere uniformly in all directions using new_size.
        // Here Vec3:splat is used to create a vector with new_size in x, y and z direction.
        transform.scale = Vec3::splat(new_size);
    }
}
examples/3d/ssr.rs (line 337)
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
fn move_camera(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut mouse_wheel_input: EventReader<MouseWheel>,
    mut cameras: Query<&mut Transform, With<Camera>>,
) {
    let (mut distance_delta, mut theta_delta) = (0.0, 0.0);

    // Handle keyboard events.
    if keyboard_input.pressed(KeyCode::KeyW) {
        distance_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
    }
    if keyboard_input.pressed(KeyCode::KeyS) {
        distance_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
    }
    if keyboard_input.pressed(KeyCode::KeyA) {
        theta_delta += CAMERA_KEYBOARD_ORBIT_SPEED;
    }
    if keyboard_input.pressed(KeyCode::KeyD) {
        theta_delta -= CAMERA_KEYBOARD_ORBIT_SPEED;
    }

    // Handle mouse events.
    for mouse_wheel_event in mouse_wheel_input.read() {
        distance_delta -= mouse_wheel_event.y * CAMERA_MOUSE_WHEEL_ZOOM_SPEED;
    }

    // Update transforms.
    for mut camera_transform in cameras.iter_mut() {
        let local_z = camera_transform.local_z().as_vec3().normalize_or_zero();
        if distance_delta != 0.0 {
            camera_transform.translation = (camera_transform.translation.length() + distance_delta)
                .clamp(CAMERA_ZOOM_RANGE.start, CAMERA_ZOOM_RANGE.end)
                * local_z;
        }
        if theta_delta != 0.0 {
            camera_transform
                .translate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, theta_delta));
            camera_transform.look_at(Vec3::ZERO, Vec3::Y);
        }
    }
}
examples/3d/visibility_range.rs (line 247)
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
fn move_camera(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut mouse_wheel_events: EventReader<MouseWheel>,
    mut cameras: Query<&mut Transform, With<Camera3d>>,
) {
    let (mut zoom_delta, mut theta_delta) = (0.0, 0.0);

    // Process zoom in and out via the keyboard.
    if keyboard_input.pressed(KeyCode::KeyW) || keyboard_input.pressed(KeyCode::ArrowUp) {
        zoom_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
    } else if keyboard_input.pressed(KeyCode::KeyS) || keyboard_input.pressed(KeyCode::ArrowDown) {
        zoom_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
    }

    // Process left and right pan via the keyboard.
    if keyboard_input.pressed(KeyCode::KeyA) || keyboard_input.pressed(KeyCode::ArrowLeft) {
        theta_delta -= CAMERA_KEYBOARD_PAN_SPEED;
    } else if keyboard_input.pressed(KeyCode::KeyD) || keyboard_input.pressed(KeyCode::ArrowRight) {
        theta_delta += CAMERA_KEYBOARD_PAN_SPEED;
    }

    // Process zoom in and out via the mouse wheel.
    for event in mouse_wheel_events.read() {
        zoom_delta -= event.y * CAMERA_MOUSE_MOVEMENT_SPEED;
    }

    // Update the camera transform.
    for transform in cameras.iter_mut() {
        let transform = transform.into_inner();

        let direction = transform.translation.normalize_or_zero();
        let magnitude = transform.translation.length();

        let new_direction = Mat3::from_rotation_y(theta_delta) * direction;
        let new_magnitude = (magnitude + zoom_delta).max(MIN_ZOOM_DISTANCE);

        transform.translation = new_direction * new_magnitude;
        transform.look_at(CAMERA_FOCAL_POINT, Vec3::Y);
    }
}
examples/games/alien_cake_addict.rs (line 304)
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
fn focus_camera(
    time: Res<Time>,
    mut game: ResMut<Game>,
    mut transforms: ParamSet<(Query<&mut Transform, With<Camera3d>>, Query<&Transform>)>,
) {
    const SPEED: f32 = 2.0;
    // if there is both a player and a bonus, target the mid-point of them
    if let (Some(player_entity), Some(bonus_entity)) = (game.player.entity, game.bonus.entity) {
        let transform_query = transforms.p1();
        if let (Ok(player_transform), Ok(bonus_transform)) = (
            transform_query.get(player_entity),
            transform_query.get(bonus_entity),
        ) {
            game.camera_should_focus = player_transform
                .translation
                .lerp(bonus_transform.translation, 0.5);
        }
        // otherwise, if there is only a player, target the player
    } else if let Some(player_entity) = game.player.entity {
        if let Ok(player_transform) = transforms.p1().get(player_entity) {
            game.camera_should_focus = player_transform.translation;
        }
        // otherwise, target the middle
    } else {
        game.camera_should_focus = Vec3::from(RESET_FOCUS);
    }
    // calculate the camera motion based on the difference between where the camera is looking
    // and where it should be looking; the greater the distance, the faster the motion;
    // smooth out the camera movement using the frame time
    let mut camera_motion = game.camera_should_focus - game.camera_is_focus;
    if camera_motion.length() > 0.2 {
        camera_motion *= SPEED * time.delta_seconds();
        // set the new camera's actual focus
        game.camera_is_focus += camera_motion;
    }
    // look at that new camera's actual focus
    for mut transform in transforms.p0().iter_mut() {
        *transform = transform.looking_at(game.camera_is_focus, Vec3::Y);
    }
}
source

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?
examples/ecs/iter_combinations.rs (line 135)
129
130
131
132
133
134
135
136
137
138
139
140
141
142
fn interact_bodies(mut query: Query<(&Mass, &GlobalTransform, &mut Acceleration)>) {
    let mut iter = query.iter_combinations_mut();
    while let Some([(Mass(m1), transform1, mut acc1), (Mass(m2), transform2, mut acc2)]) =
        iter.fetch_next()
    {
        let delta = transform2.translation() - transform1.translation();
        let distance_sq: f32 = delta.length_squared();

        let f = GRAVITY_CONSTANT / distance_sq;
        let force_unit_mass = delta * f;
        acc1.0 += force_unit_mass * *m2;
        acc2.0 -= force_unit_mass * *m1;
    }
}
More examples
Hide additional examples
examples/3d/../helpers/camera_controller.rs (line 185)
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
fn run_camera_controller(
    time: Res<Time>,
    mut windows: Query<&mut Window>,
    mut mouse_events: EventReader<MouseMotion>,
    mut scroll_events: EventReader<MouseWheel>,
    mouse_button_input: Res<ButtonInput<MouseButton>>,
    key_input: Res<ButtonInput<KeyCode>>,
    mut toggle_cursor_grab: Local<bool>,
    mut mouse_cursor_grab: Local<bool>,
    mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>,
) {
    let dt = time.delta_seconds();

    if let Ok((mut transform, mut controller)) = query.get_single_mut() {
        if !controller.initialized {
            let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
            controller.yaw = yaw;
            controller.pitch = pitch;
            controller.initialized = true;
            info!("{}", *controller);
        }
        if !controller.enabled {
            mouse_events.clear();
            return;
        }

        let mut scroll = 0.0;
        for scroll_event in scroll_events.read() {
            let amount = match scroll_event.unit {
                MouseScrollUnit::Line => scroll_event.y,
                MouseScrollUnit::Pixel => scroll_event.y / 16.0,
            };
            scroll += amount;
        }
        controller.walk_speed += scroll * controller.scroll_factor * controller.walk_speed;
        controller.run_speed = controller.walk_speed * 3.0;

        // Handle key input
        let mut axis_input = Vec3::ZERO;
        if key_input.pressed(controller.key_forward) {
            axis_input.z += 1.0;
        }
        if key_input.pressed(controller.key_back) {
            axis_input.z -= 1.0;
        }
        if key_input.pressed(controller.key_right) {
            axis_input.x += 1.0;
        }
        if key_input.pressed(controller.key_left) {
            axis_input.x -= 1.0;
        }
        if key_input.pressed(controller.key_up) {
            axis_input.y += 1.0;
        }
        if key_input.pressed(controller.key_down) {
            axis_input.y -= 1.0;
        }

        let mut cursor_grab_change = false;
        if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
            *toggle_cursor_grab = !*toggle_cursor_grab;
            cursor_grab_change = true;
        }
        if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
            *mouse_cursor_grab = true;
            cursor_grab_change = true;
        }
        if mouse_button_input.just_released(controller.mouse_key_cursor_grab) {
            *mouse_cursor_grab = false;
            cursor_grab_change = true;
        }
        let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab;

        // Apply movement update
        if axis_input != Vec3::ZERO {
            let max_speed = if key_input.pressed(controller.key_run) {
                controller.run_speed
            } else {
                controller.walk_speed
            };
            controller.velocity = axis_input.normalize() * max_speed;
        } else {
            let friction = controller.friction.clamp(0.0, 1.0);
            controller.velocity *= 1.0 - friction;
            if controller.velocity.length_squared() < 1e-6 {
                controller.velocity = Vec3::ZERO;
            }
        }
        let forward = *transform.forward();
        let right = *transform.right();
        transform.translation += controller.velocity.x * dt * right
            + controller.velocity.y * dt * Vec3::Y
            + controller.velocity.z * dt * forward;

        // Handle cursor grab
        if cursor_grab_change {
            if cursor_grab {
                for mut window in &mut windows {
                    if !window.focused {
                        continue;
                    }

                    window.cursor.grab_mode = CursorGrabMode::Locked;
                    window.cursor.visible = false;
                }
            } else {
                for mut window in &mut windows {
                    window.cursor.grab_mode = CursorGrabMode::None;
                    window.cursor.visible = true;
                }
            }
        }

        // Handle mouse input
        let mut mouse_delta = Vec2::ZERO;
        if cursor_grab {
            for mouse_event in mouse_events.read() {
                mouse_delta += mouse_event.delta;
            }
        } else {
            mouse_events.clear();
        }

        if mouse_delta != Vec2::ZERO {
            // Apply look update
            controller.pitch = (controller.pitch
                - mouse_delta.y * RADIANS_PER_DOT * controller.sensitivity)
                .clamp(-PI / 2., PI / 2.);
            controller.yaw -= mouse_delta.x * RADIANS_PER_DOT * controller.sensitivity;
            transform.rotation =
                Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
        }
    }
}
source

pub fn length_recip(self) -> f32

Computes 1.0 / length().

For valid results, self must not be of length zero.

source

pub fn distance(self, rhs: Vec3) -> f32

Computes the Euclidean distance between two points in space.

Examples found in repository?
examples/math/sampling_primitives.rs (line 509)
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
fn handle_keypress(
    mut commands: Commands,
    keyboard: Res<ButtonInput<KeyCode>>,
    mut mode: ResMut<SamplingMode>,
    mut spawn_mode: ResMut<SpawningMode>,
    samples: Query<Entity, With<SamplePoint>>,
    shapes: Res<SampledShapes>,
    mut spawn_queue: ResMut<SpawnQueue>,
    mut counter: ResMut<PointCounter>,
    mut text_menus: Query<&mut Visibility, With<Text>>,
    mut camera: Query<&mut CameraRig>,
) {
    // R => restart, deleting all samples
    if keyboard.just_pressed(KeyCode::KeyR) {
        // Don't forget to zero out the counter!
        counter.0 = 0;
        for entity in &samples {
            commands.entity(entity).despawn();
        }
    }

    // S => sample once
    if keyboard.just_pressed(KeyCode::KeyS) {
        spawn_queue.0 += 1;
    }

    // D => sample a hundred
    if keyboard.just_pressed(KeyCode::KeyD) {
        spawn_queue.0 += 100;
    }

    // M => toggle mode between interior and boundary.
    if keyboard.just_pressed(KeyCode::KeyM) {
        match *mode {
            SamplingMode::Interior => *mode = SamplingMode::Boundary,
            SamplingMode::Boundary => *mode = SamplingMode::Interior,
        }
    }

    // A => toggle spawning mode between automatic and manual.
    if keyboard.just_pressed(KeyCode::KeyA) {
        match *spawn_mode {
            SpawningMode::Manual => *spawn_mode = SpawningMode::Automatic,
            SpawningMode::Automatic => *spawn_mode = SpawningMode::Manual,
        }
    }

    // Tab => toggle help menu.
    if keyboard.just_pressed(KeyCode::Tab) {
        for mut visibility in text_menus.iter_mut() {
            *visibility = match *visibility {
                Visibility::Hidden => Visibility::Visible,
                _ => Visibility::Hidden,
            };
        }
    }

    let mut camera_rig = camera.single_mut();

    // +/- => zoom camera.
    if keyboard.just_pressed(KeyCode::NumpadSubtract) || keyboard.just_pressed(KeyCode::Minus) {
        camera_rig.distance += MAX_CAMERA_DISTANCE / 15.0;
        camera_rig.distance = camera_rig
            .distance
            .clamp(MIN_CAMERA_DISTANCE, MAX_CAMERA_DISTANCE);
    }

    if keyboard.just_pressed(KeyCode::NumpadAdd) {
        camera_rig.distance -= MAX_CAMERA_DISTANCE / 15.0;
        camera_rig.distance = camera_rig
            .distance
            .clamp(MIN_CAMERA_DISTANCE, MAX_CAMERA_DISTANCE);
    }

    // Arrows => Move camera focus
    let left = keyboard.just_pressed(KeyCode::ArrowLeft);
    let right = keyboard.just_pressed(KeyCode::ArrowRight);

    if left || right {
        let mut closest = 0;
        let mut closest_distance = f32::MAX;
        for (i, (_, position)) in shapes.0.iter().enumerate() {
            let distance = camera_rig.target.distance(*position);
            if distance < closest_distance {
                closest = i;
                closest_distance = distance;
            }
        }
        if closest > 0 && left {
            camera_rig.target = shapes.0[closest - 1].1;
        }
        if closest < shapes.0.len() - 1 && right {
            camera_rig.target = shapes.0[closest + 1].1;
        }
    }
}
source

pub fn distance_squared(self, rhs: Vec3) -> f32

Compute the squared euclidean distance between two points in space.

source

pub fn div_euclid(self, rhs: Vec3) -> Vec3

Returns the element-wise quotient of [Euclidean division] of self by rhs.

source

pub fn rem_euclid(self, rhs: Vec3) -> Vec3

Returns the element-wise remainder of Euclidean division of self by rhs.

source

pub fn normalize(self) -> Vec3

Returns self normalized to length 1.0.

For valid results, self must not be of length zero, nor very close to zero.

See also Self::try_normalize() and Self::normalize_or_zero().

Panics

Will panic if self is zero length when glam_assert is enabled.

Examples found in repository?
examples/state/custom_transitions.rs (line 189)
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
fn movement(
    time: Res<Time>,
    input: Res<ButtonInput<KeyCode>>,
    mut query: Query<&mut Transform, With<Sprite>>,
) {
    for mut transform in &mut query {
        let mut direction = Vec3::ZERO;
        if input.pressed(KeyCode::ArrowLeft) {
            direction.x -= 1.0;
        }
        if input.pressed(KeyCode::ArrowRight) {
            direction.x += 1.0;
        }
        if input.pressed(KeyCode::ArrowUp) {
            direction.y += 1.0;
        }
        if input.pressed(KeyCode::ArrowDown) {
            direction.y -= 1.0;
        }

        if direction != Vec3::ZERO {
            transform.translation += direction.normalize() * SPEED * time.delta_seconds();
        }
    }
}
More examples
Hide additional examples
examples/state/states.rs (line 151)
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
fn movement(
    time: Res<Time>,
    input: Res<ButtonInput<KeyCode>>,
    mut query: Query<&mut Transform, With<Sprite>>,
) {
    for mut transform in &mut query {
        let mut direction = Vec3::ZERO;
        if input.pressed(KeyCode::ArrowLeft) {
            direction.x -= 1.0;
        }
        if input.pressed(KeyCode::ArrowRight) {
            direction.x += 1.0;
        }
        if input.pressed(KeyCode::ArrowUp) {
            direction.y += 1.0;
        }
        if input.pressed(KeyCode::ArrowDown) {
            direction.y -= 1.0;
        }

        if direction != Vec3::ZERO {
            transform.translation += direction.normalize() * SPEED * time.delta_seconds();
        }
    }
}
examples/state/sub_states.rs (line 113)
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
fn movement(
    time: Res<Time>,
    input: Res<ButtonInput<KeyCode>>,
    mut query: Query<&mut Transform, With<Sprite>>,
) {
    for mut transform in &mut query {
        let mut direction = Vec3::ZERO;
        if input.pressed(KeyCode::ArrowLeft) {
            direction.x -= 1.0;
        }
        if input.pressed(KeyCode::ArrowRight) {
            direction.x += 1.0;
        }
        if input.pressed(KeyCode::ArrowUp) {
            direction.y += 1.0;
        }
        if input.pressed(KeyCode::ArrowDown) {
            direction.y -= 1.0;
        }

        if direction != Vec3::ZERO {
            transform.translation += direction.normalize() * SPEED * time.delta_seconds();
        }
    }
}
examples/state/computed_states.rs (line 458)
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    pub fn movement(
        time: Res<Time>,
        input: Res<ButtonInput<KeyCode>>,
        turbo: Option<Res<State<TurboMode>>>,
        mut query: Query<&mut Transform, With<Sprite>>,
    ) {
        for mut transform in &mut query {
            let mut direction = Vec3::ZERO;
            if input.pressed(KeyCode::ArrowLeft) {
                direction.x -= 1.0;
            }
            if input.pressed(KeyCode::ArrowRight) {
                direction.x += 1.0;
            }
            if input.pressed(KeyCode::ArrowUp) {
                direction.y += 1.0;
            }
            if input.pressed(KeyCode::ArrowDown) {
                direction.y -= 1.0;
            }

            if direction != Vec3::ZERO {
                transform.translation += direction.normalize()
                    * if turbo.is_some() { TURBO_SPEED } else { SPEED }
                    * time.delta_seconds();
            }
        }
    }
examples/3d/irradiance_volumes.rs (line 495)
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
fn handle_mouse_clicks(
    buttons: Res<ButtonInput<MouseButton>>,
    windows: Query<&Window, With<PrimaryWindow>>,
    cameras: Query<(&Camera, &GlobalTransform)>,
    mut main_objects: Query<&mut Transform, With<MainObject>>,
) {
    if !buttons.pressed(MouseButton::Left) {
        return;
    }
    let Some(mouse_position) = windows
        .iter()
        .next()
        .and_then(|window| window.cursor_position())
    else {
        return;
    };
    let Some((camera, camera_transform)) = cameras.iter().next() else {
        return;
    };

    // Figure out where the user clicked on the plane.
    let Some(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
        return;
    };
    let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else {
        return;
    };
    let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;

    // Move all the main objeccts.
    for mut transform in main_objects.iter_mut() {
        transform.translation = vec3(
            plane_intersection.x,
            transform.translation.y,
            plane_intersection.z,
        );
    }
}
examples/gizmos/3d_gizmos.rs (line 133)
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
fn draw_example_collection(
    mut gizmos: Gizmos,
    mut my_gizmos: Gizmos<MyRoundGizmos>,
    time: Res<Time>,
) {
    gizmos.grid(
        Vec3::ZERO,
        Quat::from_rotation_x(PI / 2.),
        UVec2::splat(20),
        Vec2::new(2., 2.),
        // Light gray
        LinearRgba::gray(0.65),
    );

    gizmos.cuboid(
        Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
        BLACK,
    );
    gizmos.rect(
        Vec3::new(time.elapsed_seconds().cos() * 2.5, 1., 0.),
        Quat::from_rotation_y(PI / 2.),
        Vec2::splat(2.),
        LIME,
    );

    gizmos.cross(Vec3::new(-1., 1., 1.), Quat::IDENTITY, 0.5, FUCHSIA);

    my_gizmos.sphere(Vec3::new(1., 0.5, 0.), Quat::IDENTITY, 0.5, RED);

    my_gizmos
        .rounded_cuboid(
            Vec3::new(-2.0, 0.75, -0.75),
            Quat::IDENTITY,
            Vec3::splat(0.9),
            TURQUOISE,
        )
        .edge_radius(0.1)
        .arc_resolution(4);

    for y in [0., 0.5, 1.] {
        gizmos.ray(
            Vec3::new(1., y, 0.),
            Vec3::new(-3., (time.elapsed_seconds() * 3.).sin(), 0.),
            BLUE,
        );
    }

    my_gizmos
        .arc_3d(
            180.0_f32.to_radians(),
            0.2,
            Vec3::ONE,
            Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
            ORANGE,
        )
        .resolution(10);

    // Circles have 32 line-segments by default.
    my_gizmos.circle(Vec3::ZERO, Dir3::Y, 3., BLACK);
    // You may want to increase this for larger circles or spheres.
    my_gizmos
        .circle(Vec3::ZERO, Dir3::Y, 3.1, NAVY)
        .resolution(64);
    my_gizmos
        .sphere(Vec3::ZERO, Quat::IDENTITY, 3.2, BLACK)
        .resolution(64);

    gizmos.arrow(Vec3::ZERO, Vec3::ONE * 1.5, YELLOW);

    // You can create more complex arrows using the arrow builder.
    gizmos
        .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
        .with_double_end()
        .with_tip_length(0.5);
}
source

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?
examples/math/render_primitives.rs (line 640)
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
fn rotate_primitive_3d_meshes(
    mut primitives_3d: Query<
        (&mut Transform, &ViewVisibility),
        (With<PrimitiveData>, With<MeshDim3>),
    >,
    time: Res<Time>,
) {
    let rotation_3d = Quat::from_rotation_arc(
        Vec3::Z,
        Vec3::new(
            time.elapsed_seconds().sin(),
            time.elapsed_seconds().cos(),
            time.elapsed_seconds().sin() * 0.5,
        )
        .try_normalize()
        .unwrap_or(Vec3::Z),
    );
    primitives_3d
        .iter_mut()
        .filter(|(_, vis)| vis.get())
        .for_each(|(mut transform, _)| {
            transform.rotation = rotation_3d;
        });
}

fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
    const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
    let rotation = Quat::from_rotation_arc(
        Vec3::Z,
        Vec3::new(
            time.elapsed_seconds().sin(),
            time.elapsed_seconds().cos(),
            time.elapsed_seconds().sin() * 0.5,
        )
        .try_normalize()
        .unwrap_or(Vec3::Z),
    );
    let color = Color::WHITE;
    let resolution = 10;

    match state.get() {
        PrimitiveSelected::RectangleAndCuboid => {
            gizmos.primitive_3d(&CUBOID, POSITION, rotation, color);
        }
        PrimitiveSelected::CircleAndSphere => drop(
            gizmos
                .primitive_3d(&SPHERE, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::Ellipse => {}
        PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, POSITION, rotation, color),
        PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, POSITION, rotation, color)),
        PrimitiveSelected::Line => gizmos.primitive_3d(&LINE3D, POSITION, rotation, color),
        PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, POSITION, rotation, color),
        PrimitiveSelected::Polyline => gizmos.primitive_3d(&POLYLINE_3D, POSITION, rotation, color),
        PrimitiveSelected::Polygon => {}
        PrimitiveSelected::RegularPolygon => {}
        PrimitiveSelected::Capsule => drop(
            gizmos
                .primitive_3d(&CAPSULE_3D, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::Cylinder => drop(
            gizmos
                .primitive_3d(&CYLINDER, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::Cone => drop(
            gizmos
                .primitive_3d(&CONE, POSITION, rotation, color)
                .resolution(resolution),
        ),
        PrimitiveSelected::ConicalFrustum => {
            gizmos.primitive_3d(&CONICAL_FRUSTUM, POSITION, rotation, color);
        }

        PrimitiveSelected::Torus => drop(
            gizmos
                .primitive_3d(&TORUS, POSITION, rotation, color)
                .minor_resolution(resolution)
                .major_resolution(resolution),
        ),
        PrimitiveSelected::Tetrahedron => {
            gizmos.primitive_3d(&TETRAHEDRON, POSITION, rotation, color);
        }

        PrimitiveSelected::Arc => {}
        PrimitiveSelected::CircularSector => {}
        PrimitiveSelected::CircularSegment => {}
    }
}
source

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().

source

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?
examples/3d/ssr.rs (line 335)
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
fn move_camera(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut mouse_wheel_input: EventReader<MouseWheel>,
    mut cameras: Query<&mut Transform, With<Camera>>,
) {
    let (mut distance_delta, mut theta_delta) = (0.0, 0.0);

    // Handle keyboard events.
    if keyboard_input.pressed(KeyCode::KeyW) {
        distance_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
    }
    if keyboard_input.pressed(KeyCode::KeyS) {
        distance_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
    }
    if keyboard_input.pressed(KeyCode::KeyA) {
        theta_delta += CAMERA_KEYBOARD_ORBIT_SPEED;
    }
    if keyboard_input.pressed(KeyCode::KeyD) {
        theta_delta -= CAMERA_KEYBOARD_ORBIT_SPEED;
    }

    // Handle mouse events.
    for mouse_wheel_event in mouse_wheel_input.read() {
        distance_delta -= mouse_wheel_event.y * CAMERA_MOUSE_WHEEL_ZOOM_SPEED;
    }

    // Update transforms.
    for mut camera_transform in cameras.iter_mut() {
        let local_z = camera_transform.local_z().as_vec3().normalize_or_zero();
        if distance_delta != 0.0 {
            camera_transform.translation = (camera_transform.translation.length() + distance_delta)
                .clamp(CAMERA_ZOOM_RANGE.start, CAMERA_ZOOM_RANGE.end)
                * local_z;
        }
        if theta_delta != 0.0 {
            camera_transform
                .translate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, theta_delta));
            camera_transform.look_at(Vec3::ZERO, Vec3::Y);
        }
    }
}
More examples
Hide additional examples
examples/3d/visibility_range.rs (line 246)
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
fn move_camera(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut mouse_wheel_events: EventReader<MouseWheel>,
    mut cameras: Query<&mut Transform, With<Camera3d>>,
) {
    let (mut zoom_delta, mut theta_delta) = (0.0, 0.0);

    // Process zoom in and out via the keyboard.
    if keyboard_input.pressed(KeyCode::KeyW) || keyboard_input.pressed(KeyCode::ArrowUp) {
        zoom_delta -= CAMERA_KEYBOARD_ZOOM_SPEED;
    } else if keyboard_input.pressed(KeyCode::KeyS) || keyboard_input.pressed(KeyCode::ArrowDown) {
        zoom_delta += CAMERA_KEYBOARD_ZOOM_SPEED;
    }

    // Process left and right pan via the keyboard.
    if keyboard_input.pressed(KeyCode::KeyA) || keyboard_input.pressed(KeyCode::ArrowLeft) {
        theta_delta -= CAMERA_KEYBOARD_PAN_SPEED;
    } else if keyboard_input.pressed(KeyCode::KeyD) || keyboard_input.pressed(KeyCode::ArrowRight) {
        theta_delta += CAMERA_KEYBOARD_PAN_SPEED;
    }

    // Process zoom in and out via the mouse wheel.
    for event in mouse_wheel_events.read() {
        zoom_delta -= event.y * CAMERA_MOUSE_MOVEMENT_SPEED;
    }

    // Update the camera transform.
    for transform in cameras.iter_mut() {
        let transform = transform.into_inner();

        let direction = transform.translation.normalize_or_zero();
        let magnitude = transform.translation.length();

        let new_direction = Mat3::from_rotation_y(theta_delta) * direction;
        let new_magnitude = (magnitude + zoom_delta).max(MIN_ZOOM_DISTANCE);

        transform.translation = new_direction * new_magnitude;
        transform.look_at(CAMERA_FOCAL_POINT, Vec3::Y);
    }
}
source

pub fn is_normalized(self) -> bool

Returns whether self is length 1.0 or not.

Uses a precision threshold of approximately 1e-4.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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?
examples/transforms/scale.rs (line 76)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
    for (mut transform, mut cube) in &mut cubes {
        // If an entity scaled beyond the maximum of its size in any dimension
        // the scaling vector is flipped so the scaling is gradually reverted.
        // Additionally, to ensure the condition does not trigger again we floor the elements to
        // their next full value, which should be max_element_size at max.
        if transform.scale.max_element() > cube.max_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.floor();
        }
        // If an entity scaled beyond the minimum of its size in any dimension
        // the scaling vector is also flipped.
        // Additionally the Values are ceiled to be min_element_size at least
        // and the scale direction is flipped.
        // This way the entity will change the dimension in which it is scaled any time it
        // reaches its min_element_size.
        if transform.scale.min_element() < cube.min_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.ceil();
            cube.scale_direction = cube.scale_direction.zxy();
        }
    }
}
source

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?
examples/transforms/scale.rs (line 86)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
    for (mut transform, mut cube) in &mut cubes {
        // If an entity scaled beyond the maximum of its size in any dimension
        // the scaling vector is flipped so the scaling is gradually reverted.
        // Additionally, to ensure the condition does not trigger again we floor the elements to
        // their next full value, which should be max_element_size at max.
        if transform.scale.max_element() > cube.max_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.floor();
        }
        // If an entity scaled beyond the minimum of its size in any dimension
        // the scaling vector is also flipped.
        // Additionally the Values are ceiled to be min_element_size at least
        // and the scale direction is flipped.
        // This way the entity will change the dimension in which it is scaled any time it
        // reaches its min_element_size.
        if transform.scale.min_element() < cube.min_element_size {
            cube.scale_direction *= -1.0;
            transform.scale = transform.scale.ceil();
            cube.scale_direction = cube.scale_direction.zxy();
        }
    }
}
source

pub fn trunc(self) -> Vec3

Returns a vector containing the integer part each element of self. This means numbers are always truncated towards zero.

source

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.

source

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.

source

pub fn exp(self) -> Vec3

Returns a vector containing e^self (the exponential function) for each element of self.

source

pub fn powf(self, n: f32) -> Vec3

Returns a vector containing each element of self raised to the power of n.

source

pub fn recip(self) -> Vec3

Returns a vector containing the reciprocal 1.0/n of each element of self.

source

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?
examples/gizmos/axes.rs (line 219)
218
219
220
221
222
223
224
225
226
227
228
fn interpolate_transforms(t1: Transform, t2: Transform, t: f32) -> Transform {
    let translation = t1.translation.lerp(t2.translation, t);
    let rotation = t1.rotation.slerp(t2.rotation, t);
    let scale = elerp(t1.scale, t2.scale, t);

    Transform {
        translation,
        rotation,
        scale,
    }
}
More examples
Hide additional examples
examples/3d/parallax_mapping.rs (line 193)
183
184
185
186
187
188
189
190
191
192
193
194
195
fn move_camera(
    mut camera: Query<&mut Transform, With<CameraController>>,
    mut current_view: Local<usize>,
    button: Res<ButtonInput<MouseButton>>,
) {
    let mut camera = camera.single_mut();
    if button.just_pressed(MouseButton::Left) {
        *current_view = (*current_view + 1) % CAMERA_POSITIONS.len();
    }
    let target = CAMERA_POSITIONS[*current_view];
    camera.translation = camera.translation.lerp(target.translation, 0.2);
    camera.rotation = camera.rotation.slerp(target.rotation, 0.2);
}
examples/games/alien_cake_addict.rs (line 289)
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
fn focus_camera(
    time: Res<Time>,
    mut game: ResMut<Game>,
    mut transforms: ParamSet<(Query<&mut Transform, With<Camera3d>>, Query<&Transform>)>,
) {
    const SPEED: f32 = 2.0;
    // if there is both a player and a bonus, target the mid-point of them
    if let (Some(player_entity), Some(bonus_entity)) = (game.player.entity, game.bonus.entity) {
        let transform_query = transforms.p1();
        if let (Ok(player_transform), Ok(bonus_transform)) = (
            transform_query.get(player_entity),
            transform_query.get(bonus_entity),
        ) {
            game.camera_should_focus = player_transform
                .translation
                .lerp(bonus_transform.translation, 0.5);
        }
        // otherwise, if there is only a player, target the player
    } else if let Some(player_entity) = game.player.entity {
        if let Ok(player_transform) = transforms.p1().get(player_entity) {
            game.camera_should_focus = player_transform.translation;
        }
        // otherwise, target the middle
    } else {
        game.camera_should_focus = Vec3::from(RESET_FOCUS);
    }
    // calculate the camera motion based on the difference between where the camera is looking
    // and where it should be looking; the greater the distance, the faster the motion;
    // smooth out the camera movement using the frame time
    let mut camera_motion = game.camera_should_focus - game.camera_is_focus;
    if camera_motion.length() > 0.2 {
        camera_motion *= SPEED * time.delta_seconds();
        // set the new camera's actual focus
        game.camera_is_focus += camera_motion;
    }
    // look at that new camera's actual focus
    for mut transform in transforms.p0().iter_mut() {
        *transform = transform.looking_at(game.camera_is_focus, Vec3::Y);
    }
}
source

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.

source

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.

source

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.

source

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 when glam_assert is enabled.

source

pub fn clamp_length_max(self, max: f32) -> Vec3

Returns a vector with a length no more than max

source

pub fn clamp_length_min(self, min: f32) -> Vec3

Returns a vector with a length no less than min

source

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.

source

pub fn angle_between(self, rhs: Vec3) -> f32

Returns the angle (in radians) between two vectors.

The inputs do not need to be unit vectors however they must be non-zero.

source

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.

source

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.

source

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.

source

pub fn as_dvec3(&self) -> DVec3

Casts all elements of self to f64.

source

pub fn as_i16vec3(&self) -> I16Vec3

Casts all elements of self to i16.

source

pub fn as_u16vec3(&self) -> U16Vec3

Casts all elements of self to u16.

source

pub fn as_ivec3(&self) -> IVec3

Casts all elements of self to i32.

source

pub fn as_uvec3(&self) -> UVec3

Casts all elements of self to u32.

source

pub fn as_i64vec3(&self) -> I64Vec3

Casts all elements of self to i64.

source

pub fn as_u64vec3(&self) -> U64Vec3

Casts all elements of self to u64.

Trait Implementations§

source§

impl Add<Vec3> for f32

§

type Output = Vec3

The resulting type after applying the + operator.
source§

fn add(self, rhs: Vec3) -> Vec3

Performs the + operation. Read more
source§

impl Add<f32> for Vec3

§

type Output = Vec3

The resulting type after applying the + operator.
source§

fn add(self, rhs: f32) -> Vec3

Performs the + operation. Read more
source§

impl Add for Vec3

§

type Output = Vec3

The resulting type after applying the + operator.
source§

fn add(self, rhs: Vec3) -> Vec3

Performs the + operation. Read more
source§

impl AddAssign<f32> for Vec3

source§

fn add_assign(&mut self, rhs: f32)

Performs the += operation. Read more
source§

impl AddAssign for Vec3

source§

fn add_assign(&mut self, rhs: Vec3)

Performs the += operation. Read more
§

impl Animatable for Vec3

§

fn interpolate(a: &Vec3, b: &Vec3, t: f32) -> Vec3

Interpolates between a and b with a interpolation factor of time. Read more
§

fn blend(inputs: impl Iterator<Item = BlendInput<Vec3>>) -> Vec3

Blends one or more values together. Read more
§

fn post_process(&mut self, _world: &World)

Post-processes the value using resources in the World. Most animatable types do not need to implement this.
source§

impl AsMut<[f32; 3]> for Vec3

Available on non-target_arch="spirv" only.
source§

fn as_mut(&mut self) -> &mut [f32; 3]

Converts this type into a mutable reference of the (usually inferred) input type.
§

impl AsMutVectorParts<f32, 3> for Vec3
where Vec3: AsMut<[f32; 3]>, f32: VectorScalar,

§

fn as_mut_parts(&mut self) -> &mut [f32; 3]

source§

impl AsRef<[f32; 3]> for Vec3

Available on non-target_arch="spirv" only.
source§

fn as_ref(&self) -> &[f32; 3]

Converts this type into a shared reference of the (usually inferred) input type.
§

impl AsRefVectorParts<f32, 3> for Vec3
where Vec3: AsRef<[f32; 3]>, f32: VectorScalar,

§

fn as_ref_parts(&self) -> &[f32; 3]

source§

impl Clone for Vec3

source§

fn clone(&self) -> Vec3

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl CreateFrom for Vec3

§

fn create_from<B>(reader: &mut Reader<B>) -> Vec3
where B: BufferRef,

source§

impl Debug for Vec3

Available on non-target_arch="spirv" only.
source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Default for Vec3

source§

fn default() -> Vec3

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for Vec3

source§

fn deserialize<D>( deserializer: D, ) -> Result<Vec3, <D as Deserializer<'de>>::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Vec3

Available on non-target_arch="spirv" only.
source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Div<Vec3> for f32

§

type Output = Vec3

The resulting type after applying the / operator.
source§

fn div(self, rhs: Vec3) -> Vec3

Performs the / operation. Read more
source§

impl Div<f32> for Vec3

§

type Output = Vec3

The resulting type after applying the / operator.
source§

fn div(self, rhs: f32) -> Vec3

Performs the / operation. Read more
source§

impl Div for Vec3

§

type Output = Vec3

The resulting type after applying the / operator.
source§

fn div(self, rhs: Vec3) -> Vec3

Performs the / operation. Read more
source§

impl DivAssign<f32> for Vec3

source§

fn div_assign(&mut self, rhs: f32)

Performs the /= operation. Read more
source§

impl DivAssign for Vec3

source§

fn div_assign(&mut self, rhs: Vec3)

Performs the /= operation. Read more
source§

impl From<[f32; 3]> for Vec3

source§

fn from(a: [f32; 3]) -> Vec3

Converts to this type from the input type.
source§

impl From<(Vec2, f32)> for Vec3

source§

fn from(_: (Vec2, f32)) -> Vec3

Converts to this type from the input type.
source§

impl From<(f32, f32, f32)> for Vec3

source§

fn from(t: (f32, f32, f32)) -> Vec3

Converts to this type from the input type.
source§

impl From<BVec3> for Vec3

source§

fn from(v: BVec3) -> Vec3

Converts to this type from the input type.
source§

impl From<BVec3A> for Vec3

source§

fn from(v: BVec3A) -> Vec3

Converts to this type from the input type.
§

impl From<Dir3> for Vec3

§

fn from(value: Dir3) -> Vec3

Converts to this type from the input type.
source§

impl From<Vec3> for [f32; 3]

source§

fn from(v: Vec3) -> [f32; 3]

Converts to this type from the input type.
source§

impl From<Vec3> for (f32, f32, f32)

source§

fn from(v: Vec3) -> (f32, f32, f32)

Converts to this type from the input type.
source§

impl From<Vec3> for DVec3

source§

fn from(v: Vec3) -> DVec3

Converts to this type from the input type.
source§

impl From<Vec3> for Vec3A

source§

fn from(v: Vec3) -> Vec3A

Converts to this type from the input type.
source§

impl From<Vec3A> for Vec3

source§

fn from(v: Vec3A) -> Vec3

Converts to this type from the input type.
§

impl FromIterator<Vec3> for BoxedPolyline3d

§

fn from_iter<I>(iter: I) -> BoxedPolyline3d
where I: IntoIterator<Item = Vec3>,

Creates a value from an iterator. Read more
§

impl<const N: usize> FromIterator<Vec3> for Polyline3d<N>

§

fn from_iter<I>(iter: I) -> Polyline3d<N>
where I: IntoIterator<Item = Vec3>,

Creates a value from an iterator. Read more
§

impl FromReflect for Vec3
where Vec3: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<Vec3>

Constructs a concrete instance of Self from a reflected value.
§

fn take_from_reflect( reflect: Box<dyn Reflect>, ) -> Result<Self, Box<dyn Reflect>>

Attempts to downcast the given value to Self using, constructing the value using from_reflect if that fails. Read more
§

impl FromVectorParts<f32, 3> for Vec3
where Vec3: From<[f32; 3]>, f32: VectorScalar,

§

fn from_parts(parts: [f32; 3]) -> Vec3

§

impl GetTypeRegistration for Vec3
where Vec3: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn get_type_registration() -> TypeRegistration

Returns the default TypeRegistration for this type.
§

fn register_type_dependencies(registry: &mut TypeRegistry)

Registers other types needed by this type. Read more
source§

impl Index<usize> for Vec3

§

type Output = f32

The returned type after indexing.
source§

fn index(&self, index: usize) -> &<Vec3 as Index<usize>>::Output

Performs the indexing (container[index]) operation. Read more
source§

impl IndexMut<usize> for Vec3

source§

fn index_mut(&mut self, index: usize) -> &mut <Vec3 as Index<usize>>::Output

Performs the mutable indexing (container[index]) operation. Read more
§

impl Mul<Vec3> for GlobalTransform

§

type Output = Vec3

The resulting type after applying the * operator.
§

fn mul(self, value: Vec3) -> <GlobalTransform as Mul<Vec3>>::Output

Performs the * operation. Read more
source§

impl Mul<Vec3> for Mat3

§

type Output = Vec3

The resulting type after applying the * operator.
source§

fn mul(self, rhs: Vec3) -> <Mat3 as Mul<Vec3>>::Output

Performs the * operation. Read more
source§

impl Mul<Vec3> for Mat3A

§

type Output = Vec3

The resulting type after applying the * operator.
source§

fn mul(self, rhs: Vec3) -> Vec3

Performs the * operation. Read more
source§

impl Mul<Vec3> for Quat

source§

fn mul(self, rhs: Vec3) -> <Quat as Mul<Vec3>>::Output

Multiplies a quaternion and a 3D vector, returning the rotated vector.

§Panics

Will panic if self is not normalized when glam_assert is enabled.

§

type Output = Vec3

The resulting type after applying the * operator.
§

impl Mul<Vec3> for Transform

§

type Output = Vec3

The resulting type after applying the * operator.
§

fn mul(self, value: Vec3) -> <Transform as Mul<Vec3>>::Output

Performs the * operation. Read more
source§

impl Mul<Vec3> for f32

§

type Output = Vec3

The resulting type after applying the * operator.
source§

fn mul(self, rhs: Vec3) -> Vec3

Performs the * operation. Read more
source§

impl Mul<f32> for Vec3

§

type Output = Vec3

The resulting type after applying the * operator.
source§

fn mul(self, rhs: f32) -> Vec3

Performs the * operation. Read more
source§

impl Mul for Vec3

§

type Output = Vec3

The resulting type after applying the * operator.
source§

fn mul(self, rhs: Vec3) -> Vec3

Performs the * operation. Read more
source§

impl MulAssign<f32> for Vec3

source§

fn mul_assign(&mut self, rhs: f32)

Performs the *= operation. Read more
source§

impl MulAssign for Vec3

source§

fn mul_assign(&mut self, rhs: Vec3)

Performs the *= operation. Read more
source§

impl Neg for Vec3

§

type Output = Vec3

The resulting type after applying the - operator.
source§

fn neg(self) -> Vec3

Performs the unary - operation. Read more
§

impl NormedVectorSpace for Vec3

§

fn norm(self) -> f32

The size of this element. The return value should always be nonnegative.
§

fn norm_squared(self) -> f32

The squared norm of this element. Computing this is often faster than computing NormedVectorSpace::norm.
§

fn distance(self, rhs: Self) -> f32

The distance between this element and another, as determined by the norm.
§

fn distance_squared(self, rhs: Self) -> f32

The squared distance between this element and another, as determined by the norm. Note that this is often faster to compute in practice than NormedVectorSpace::distance.
source§

impl PartialEq for Vec3

source§

fn eq(&self, other: &Vec3) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<'a> Product<&'a Vec3> for Vec3

source§

fn product<I>(iter: I) -> Vec3
where I: Iterator<Item = &'a Vec3>,

Method which takes an iterator and generates Self from the elements by multiplying the items.
source§

impl Product for Vec3

source§

fn product<I>(iter: I) -> Vec3
where I: Iterator<Item = Vec3>,

Method which takes an iterator and generates Self from the elements by multiplying the items.
§

impl ReadFrom for Vec3

§

fn read_from<B>(&mut self, reader: &mut Reader<B>)
where B: BufferRef,

§

impl Reflect for Vec3
where Vec3: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn get_represented_type_info(&self) -> Option<&'static TypeInfo>

Returns the TypeInfo of the type represented by this value. Read more
§

fn into_any(self: Box<Vec3>) -> Box<dyn Any>

Returns the value as a Box<dyn Any>.
§

fn as_any(&self) -> &(dyn Any + 'static)

Returns the value as a &dyn Any.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Returns the value as a &mut dyn Any.
§

fn into_reflect(self: Box<Vec3>) -> Box<dyn Reflect>

Casts this type to a boxed reflected value.
§

fn as_reflect(&self) -> &(dyn Reflect + 'static)

Casts this type to a reflected value.
§

fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)

Casts this type to a mutable reflected value.
§

fn clone_value(&self) -> Box<dyn Reflect>

Clones the value as a Reflect trait object. Read more
§

fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>

Performs a type-checked assignment of a reflected value to this value. Read more
§

fn try_apply( &mut self, value: &(dyn Reflect + 'static), ) -> Result<(), ApplyError>

Tries to apply a reflected value to this value. Read more
§

fn reflect_kind(&self) -> ReflectKind

Returns a zero-sized enumeration of “kinds” of type. Read more
§

fn reflect_ref(&self) -> ReflectRef<'_>

Returns an immutable enumeration of “kinds” of type. Read more
§

fn reflect_mut(&mut self) -> ReflectMut<'_>

Returns a mutable enumeration of “kinds” of type. Read more
§

fn reflect_owned(self: Box<Vec3>) -> ReflectOwned

Returns an owned enumeration of “kinds” of type. Read more
§

fn reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>

Returns a “partial equality” comparison result. Read more
§

fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Debug formatter for the value. Read more
§

fn apply(&mut self, value: &(dyn Reflect + 'static))

Applies a reflected value to this value. Read more
§

fn reflect_hash(&self) -> Option<u64>

Returns a hash of the value (which includes the type). Read more
§

fn serializable(&self) -> Option<Serializable<'_>>

Returns a serializable version of the value. Read more
§

fn is_dynamic(&self) -> bool

Indicates whether or not this type is a dynamic type. Read more
source§

impl Rem<Vec3> for f32

§

type Output = Vec3

The resulting type after applying the % operator.
source§

fn rem(self, rhs: Vec3) -> Vec3

Performs the % operation. Read more
source§

impl Rem<f32> for Vec3

§

type Output = Vec3

The resulting type after applying the % operator.
source§

fn rem(self, rhs: f32) -> Vec3

Performs the % operation. Read more
source§

impl Rem for Vec3

§

type Output = Vec3

The resulting type after applying the % operator.
source§

fn rem(self, rhs: Vec3) -> Vec3

Performs the % operation. Read more
source§

impl RemAssign<f32> for Vec3

source§

fn rem_assign(&mut self, rhs: f32)

Performs the %= operation. Read more
source§

impl RemAssign for Vec3

source§

fn rem_assign(&mut self, rhs: Vec3)

Performs the %= operation. Read more
source§

impl Serialize for Vec3

source§

fn serialize<S>( &self, serializer: S, ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more
§

impl ShaderSize for Vec3
where f32: ShaderSize,

§

const SHADER_SIZE: NonZero<u64> = _

Represents WGSL Size (equivalent to ShaderType::min_size)
§

impl ShaderType for Vec3
where f32: ShaderSize,

§

fn min_size() -> NonZero<u64>

Represents the minimum size of Self (equivalent to GPUBufferBindingLayout.minBindingSize) Read more
§

fn size(&self) -> NonZero<u64>

Returns the size of Self at runtime Read more
§

fn assert_uniform_compat()

§

impl Struct for Vec3
where Vec3: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>

Returns a reference to the value of the field named name as a &dyn Reflect.
§

fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>

Returns a mutable reference to the value of the field named name as a &mut dyn Reflect.
§

fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>

Returns a reference to the value of the field with index index as a &dyn Reflect.
§

fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>

Returns a mutable reference to the value of the field with index index as a &mut dyn Reflect.
§

fn name_at(&self, index: usize) -> Option<&str>

Returns the name of the field with index index.
§

fn field_len(&self) -> usize

Returns the number of fields in the struct.
§

fn iter_fields(&self) -> FieldIter<'_>

Returns an iterator over the values of the reflectable fields for this struct.
§

fn clone_dynamic(&self) -> DynamicStruct

Clones the struct into a DynamicStruct.
source§

impl Sub<Vec3> for f32

§

type Output = Vec3

The resulting type after applying the - operator.
source§

fn sub(self, rhs: Vec3) -> Vec3

Performs the - operation. Read more
source§

impl Sub<f32> for Vec3

§

type Output = Vec3

The resulting type after applying the - operator.
source§

fn sub(self, rhs: f32) -> Vec3

Performs the - operation. Read more
source§

impl Sub for Vec3

§

type Output = Vec3

The resulting type after applying the - operator.
source§

fn sub(self, rhs: Vec3) -> Vec3

Performs the - operation. Read more
source§

impl SubAssign<f32> for Vec3

source§

fn sub_assign(&mut self, rhs: f32)

Performs the -= operation. Read more
source§

impl SubAssign for Vec3

source§

fn sub_assign(&mut self, rhs: Vec3)

Performs the -= operation. Read more
source§

impl<'a> Sum<&'a Vec3> for Vec3

source§

fn sum<I>(iter: I) -> Vec3
where I: Iterator<Item = &'a Vec3>,

Method which takes an iterator and generates Self from the elements by “summing up” the items.
source§

impl Sum for Vec3

source§

fn sum<I>(iter: I) -> Vec3
where I: Iterator<Item = Vec3>,

Method which takes an iterator and generates Self from the elements by “summing up” the items.
§

impl TryFrom<Vec3> for Dir3

§

type Error = InvalidDirectionError

The type returned in the event of a conversion error.
§

fn try_from(value: Vec3) -> Result<Dir3, <Dir3 as TryFrom<Vec3>>::Error>

Performs the conversion.
§

impl TypePath for Vec3
where Vec3: Any + Send + Sync,

§

fn type_path() -> &'static str

Returns the fully qualified path of the underlying type. Read more
§

fn short_type_path() -> &'static str

Returns a short, pretty-print enabled path to the type. Read more
§

fn type_ident() -> Option<&'static str>

Returns the name of the type, or None if it is anonymous. Read more
§

fn crate_name() -> Option<&'static str>

Returns the name of the crate the type is in, or None if it is anonymous. Read more
§

fn module_path() -> Option<&'static str>

Returns the path to the module the type is in, or None if it is anonymous. Read more
§

impl Typed for Vec3
where Vec3: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn type_info() -> &'static TypeInfo

Returns the compile-time info for the underlying type.
source§

impl Vec3Swizzles for Vec3

§

type Vec2 = Vec2

§

type Vec4 = Vec4

source§

fn xx(self) -> Vec2

source§

fn xy(self) -> Vec2

source§

fn xz(self) -> Vec2

source§

fn yx(self) -> Vec2

source§

fn yy(self) -> Vec2

source§

fn yz(self) -> Vec2

source§

fn zx(self) -> Vec2

source§

fn zy(self) -> Vec2

source§

fn zz(self) -> Vec2

source§

fn xxx(self) -> Vec3

source§

fn xxy(self) -> Vec3

source§

fn xxz(self) -> Vec3

source§

fn xyx(self) -> Vec3

source§

fn xyy(self) -> Vec3

source§

fn xyz(self) -> Vec3

source§

fn xzx(self) -> Vec3

source§

fn xzy(self) -> Vec3

source§

fn xzz(self) -> Vec3

source§

fn yxx(self) -> Vec3

source§

fn yxy(self) -> Vec3

source§

fn yxz(self) -> Vec3

source§

fn yyx(self) -> Vec3

source§

fn yyy(self) -> Vec3

source§

fn yyz(self) -> Vec3

source§

fn yzx(self) -> Vec3

source§

fn yzy(self) -> Vec3

source§

fn yzz(self) -> Vec3

source§

fn zxx(self) -> Vec3

source§

fn zxy(self) -> Vec3

source§

fn zxz(self) -> Vec3

source§

fn zyx(self) -> Vec3

source§

fn zyy(self) -> Vec3

source§

fn zyz(self) -> Vec3

source§

fn zzx(self) -> Vec3

source§

fn zzy(self) -> Vec3

source§

fn zzz(self) -> Vec3

source§

fn xxxx(self) -> Vec4

source§

fn xxxy(self) -> Vec4

source§

fn xxxz(self) -> Vec4

source§

fn xxyx(self) -> Vec4

source§

fn xxyy(self) -> Vec4

source§

fn xxyz(self) -> Vec4

source§

fn xxzx(self) -> Vec4

source§

fn xxzy(self) -> Vec4

source§

fn xxzz(self) -> Vec4

source§

fn xyxx(self) -> Vec4

source§

fn xyxy(self) -> Vec4

source§

fn xyxz(self) -> Vec4

source§

fn xyyx(self) -> Vec4

source§

fn xyyy(self) -> Vec4

source§

fn xyyz(self) -> Vec4

source§

fn xyzx(self) -> Vec4

source§

fn xyzy(self) -> Vec4

source§

fn xyzz(self) -> Vec4

source§

fn xzxx(self) -> Vec4

source§

fn xzxy(self) -> Vec4

source§

fn xzxz(self) -> Vec4

source§

fn xzyx(self) -> Vec4

source§

fn xzyy(self) -> Vec4

source§

fn xzyz(self) -> Vec4

source§

fn xzzx(self) -> Vec4

source§

fn xzzy(self) -> Vec4

source§

fn xzzz(self) -> Vec4

source§

fn yxxx(self) -> Vec4

source§

fn yxxy(self) -> Vec4

source§

fn yxxz(self) -> Vec4

source§

fn yxyx(self) -> Vec4

source§

fn yxyy(self) -> Vec4

source§

fn yxyz(self) -> Vec4

source§

fn yxzx(self) -> Vec4

source§

fn yxzy(self) -> Vec4

source§

fn yxzz(self) -> Vec4

source§

fn yyxx(self) -> Vec4

source§

fn yyxy(self) -> Vec4

source§

fn yyxz(self) -> Vec4

source§

fn yyyx(self) -> Vec4

source§

fn yyyy(self) -> Vec4

source§

fn yyyz(self) -> Vec4

source§

fn yyzx(self) -> Vec4

source§

fn yyzy(self) -> Vec4

source§

fn yyzz(self) -> Vec4

source§

fn yzxx(self) -> Vec4

source§

fn yzxy(self) -> Vec4

source§

fn yzxz(self) -> Vec4

source§

fn yzyx(self) -> Vec4

source§

fn yzyy(self) -> Vec4

source§

fn yzyz(self) -> Vec4

source§

fn yzzx(self) -> Vec4

source§

fn yzzy(self) -> Vec4

source§

fn yzzz(self) -> Vec4

source§

fn zxxx(self) -> Vec4

source§

fn zxxy(self) -> Vec4

source§

fn zxxz(self) -> Vec4

source§

fn zxyx(self) -> Vec4

source§

fn zxyy(self) -> Vec4

source§

fn zxyz(self) -> Vec4

source§

fn zxzx(self) -> Vec4

source§

fn zxzy(self) -> Vec4

source§

fn zxzz(self) -> Vec4

source§

fn zyxx(self) -> Vec4

source§

fn zyxy(self) -> Vec4

source§

fn zyxz(self) -> Vec4

source§

fn zyyx(self) -> Vec4

source§

fn zyyy(self) -> Vec4

source§

fn zyyz(self) -> Vec4

source§

fn zyzx(self) -> Vec4

source§

fn zyzy(self) -> Vec4

source§

fn zyzz(self) -> Vec4

source§

fn zzxx(self) -> Vec4

source§

fn zzxy(self) -> Vec4

source§

fn zzxz(self) -> Vec4

source§

fn zzyx(self) -> Vec4

source§

fn zzyy(self) -> Vec4

source§

fn zzyz(self) -> Vec4

source§

fn zzzx(self) -> Vec4

source§

fn zzzy(self) -> Vec4

source§

fn zzzz(self) -> Vec4

§

impl VectorSpace for Vec3

§

const ZERO: Vec3 = Vec3::ZERO

The zero vector, which is the identity of addition for the vector space type.
§

fn lerp(&self, rhs: Self, t: f32) -> Self

Perform vector space linear interpolation between this element and another, based on the parameter t. When t is 0, self is recovered. When t is 1, rhs is recovered. Read more
§

impl WriteInto for Vec3

§

fn write_into<B>(&self, writer: &mut Writer<B>)
where B: BufferMut,

source§

impl Zeroable for Vec3

§

fn zeroed() -> Self

source§

impl Copy for Vec3

source§

impl Pod for Vec3

source§

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> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> CheckedBitPattern for T
where T: AnyBitPattern,

§

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.
§

fn is_valid_bit_pattern(_bits: &T) -> bool

If this function returns true, then it must be valid to reinterpret bits as &Self.
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
§

impl<T> DynamicTypePath for T
where T: TypePath,

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

impl<T> FromWorld for T
where T: Default,

§

fn from_world(_world: &mut World) -> T

Creates Self using data from the given World.
§

impl<S> GetField for S
where S: Struct,

§

fn get_field<T>(&self, name: &str) -> Option<&T>
where T: Reflect,

Returns a reference to the value of the field named name, downcast to T.
§

fn get_field_mut<T>(&mut self, name: &str) -> Option<&mut T>
where T: Reflect,

Returns a mutable reference to the value of the field named name, downcast to T.
§

impl<T> GetPath for T
where T: Reflect + ?Sized,

§

fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn Reflect + 'static), ReflectPathError<'p>>

Returns a reference to the value specified by path. Read more
§

fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>

Returns a mutable reference to the value specified by path. Read more
§

fn path<'p, T>( &self, path: impl ReflectPath<'p>, ) -> Result<&T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed reference to the value specified by path. Read more
§

fn path_mut<'p, T>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed mutable reference to the value specified by path. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

§

fn into_sample(self) -> T

§

impl<T> NoneValue for T
where T: Default,

§

type NoneType = T

§

fn null_value() -> T

The none-equivalent value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

§

impl<V> StableInterpolate for V

§

fn interpolate_stable(&self, other: &V, t: f32) -> V

Interpolate between this value and the 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.
§

fn interpolate_stable_assign(&mut self, other: &Self, t: f32)

A version of interpolate_stable that assigns the result to self for convenience.
§

fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32)

Smoothly nudge this value towards the 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 more
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

§

fn to_sample_(self) -> U

§

impl<T> ToSmolStr for T
where T: Display + ?Sized,

§

fn to_smolstr(&self) -> SmolStr

source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

§

fn clone_type_data(&self) -> Box<dyn TypeData>

§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
§

impl<T> AnyBitPattern for T
where T: Pod,

§

impl<T> ConditionalSend for T
where T: Send,

source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

§

impl<T> GpuArrayBufferable for T

§

impl<T> NoUninit for T
where T: Pod,

source§

impl<T, Rhs> NumAssignOps<Rhs> for T
where T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>,

source§

impl<T, Rhs, Output> NumOps<Rhs, Output> for T
where T: Sub<Rhs, Output = Output> + Mul<Rhs, Output = Output> + Div<Rhs, Output = Output> + Add<Rhs, Output = Output> + Rem<Rhs, Output = Output>,

§

impl<T> Settings for T
where T: 'static + Send + Sync,

§

impl<T> WasmNotSend for T
where T: Send,

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

impl<T> WasmNotSync for T
where T: Sync,