#[repr(C)]pub struct Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
Expand description
A 3-dimensional vector.
Fields§
§x: f32
§y: f32
§z: f32
Implementations§
source§impl Vec3
impl Vec3
sourcepub const NEG_INFINITY: Vec3 = _
pub const NEG_INFINITY: Vec3 = _
All f32::NEG_INFINITY
.
sourcepub const fn new(x: f32, y: f32, z: f32) -> Vec3
pub const fn new(x: f32, y: f32, z: f32) -> Vec3
Creates a new vector.
Examples found in repository?
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,
));
}
}
}
More examples
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 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
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: Triangle2d = Triangle2d {
vertices: [
Vec2::new(SMALL_2D, 0.0),
Vec2::new(0.0, SMALL_2D),
Vec2::new(-SMALL_2D, 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 TORUS: Torus = Torus {
minor_radius: SMALL_3D / 2.0,
major_radius: SMALL_3D * 1.5,
};
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,
asset_server: Res<AssetServer>,
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 font_size = 24.0;
let font: Handle<Font> = asset_server.load("fonts/FiraMono-Medium.ttf");
let style = TextStyle {
font,
font_size,
color: Color::WHITE,
};
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 => gizmos.primitive_2d(ELLIPSE, POSITION, angle, color),
PrimitiveSelected::Triangle => gizmos.primitive_2d(TRIANGLE, 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 => {}
}
}
/// 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()),
Some(CIRCLE.mesh().build()),
Some(ELLIPSE.mesh().build()),
Some(TRIANGLE.mesh()),
None, // plane
None, // line
None, // segment
None, // polyline
None, // polygon
Some(REGULAR_POLYGON.mesh()),
Some(CAPSULE_2D.mesh().build()),
None, // cylinder
None, // cone
None, // conical frustum
None, // torus
]
.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()),
Some(SPHERE.mesh().build()),
None, // ellipse
None, // triangle
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()),
]
.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 segments = 10;
match state.get() {
PrimitiveSelected::RectangleAndCuboid => {
gizmos.primitive_3d(CUBOID, POSITION, rotation, color);
}
PrimitiveSelected::CircleAndSphere => drop(
gizmos
.primitive_3d(SPHERE, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Ellipse => {}
PrimitiveSelected::Triangle => {}
PrimitiveSelected::Plane => drop(gizmos.primitive_3d(PLANE_3D, POSITION, rotation, color)),
PrimitiveSelected::Line => gizmos.primitive_3d(LINE3D, POSITION, rotation, color),
PrimitiveSelected::Segment => gizmos.primitive_3d(SEGMENT_3D, POSITION, rotation, color),
PrimitiveSelected::Polyline => gizmos.primitive_3d(POLYLINE_3D, POSITION, rotation, color),
PrimitiveSelected::Polygon => {}
PrimitiveSelected::RegularPolygon => {}
PrimitiveSelected::Capsule => drop(
gizmos
.primitive_3d(CAPSULE_3D, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Cylinder => drop(
gizmos
.primitive_3d(CYLINDER, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Cone => drop(
gizmos
.primitive_3d(CONE, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::ConicalFrustum => {
gizmos.primitive_3d(CONICAL_FRUSTUM, POSITION, rotation, color);
}
PrimitiveSelected::Torus => drop(
gizmos
.primitive_3d(TORUS, POSITION, rotation, color)
.minor_segments(segments)
.major_segments(segments),
),
}
}
72 73 74 75 76 77 78 79 80 81 82 83
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();
}
}
}
20 21 22 23 24 25 26 27 28 29 30 31 32 33
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("models/SimpleSkin/SimpleSkin.gltf#Scene0"),
..default()
});
}
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
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()
});
}
- examples/shader/array_texture.rs
- examples/shader/fallback_image.rs
- examples/3d/parallax_mapping.rs
- examples/shader/texture_binding_array.rs
- examples/2d/sprite_slice.rs
- examples/stress_tests/bevymark.rs
- examples/3d/atmospheric_fog.rs
- examples/3d/tonemapping.rs
- examples/animation/animation_graph.rs
- examples/3d/animated_material.rs
- examples/games/loading_screen.rs
- examples/shader/post_processing.rs
- examples/3d/lines.rs
- examples/3d/load_gltf.rs
- examples/3d/update_gltf_scene.rs
- examples/shader/shader_instancing.rs
- examples/animation/cubic_curve.rs
- examples/2d/mesh2d_vertex_color_texture.rs
- examples/gizmos/3d_gizmos.rs
- examples/3d/motion_blur.rs
- examples/3d/3d_shapes.rs
- examples/gizmos/axes.rs
- examples/games/contributors.rs
- examples/2d/bloom_2d.rs
- examples/audio/spatial_audio_2d.rs
- examples/3d/fog.rs
- examples/2d/sprite_animation.rs
- examples/animation/animated_fox.rs
- examples/stress_tests/many_lights.rs
- examples/3d/shadow_caster_receiver.rs
- examples/games/alien_cake_addict.rs
- examples/time/virtual_time.rs
- examples/3d/anti_aliasing.rs
- examples/ecs/iter_combinations.rs
- examples/tools/scene_viewer/main.rs
- examples/3d/meshlet.rs
- examples/3d/render_to_texture.rs
- examples/3d/spotlight.rs
- examples/shader/shader_prepass.rs
- examples/stress_tests/many_foxes.rs
- examples/animation/custom_skinned_mesh.rs
- examples/2d/texture_atlas.rs
- examples/2d/text2d.rs
- examples/games/desk_toy.rs
- examples/3d/split_screen.rs
- examples/3d/shadow_biases.rs
- examples/3d/deferred_rendering.rs
- examples/stress_tests/many_cubes.rs
- examples/animation/animated_transform.rs
- examples/3d/lighting.rs
- examples/3d/transmission.rs
sourcepub const fn splat(v: f32) -> Vec3
pub const fn splat(v: f32) -> Vec3
Creates a vector with all elements set to v
.
Examples found in repository?
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
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, asset_server: &AssetServer) {
commands.spawn(
TextBundle {
text: app_status.create_text(asset_server),
..TextBundle::default()
}
.with_style(Style {
position_type: PositionType::Absolute,
bottom: Val::Px(10.0),
left: Val::Px(10.0),
..default()
}),
);
}
// A system that updates the help text.
fn update_text(
mut text_query: Query<&mut Text>,
app_status: Res<AppStatus>,
asset_server: Res<AssetServer>,
) {
for mut text in text_query.iter_mut() {
*text = app_status.create_text(&asset_server);
}
}
impl AppStatus {
// Constructs the help text at the bottom of the screen based on the
// application status.
fn create_text(&self, asset_server: &AssetServer) -> 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 {
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
font_size: 24.0,
..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("models/animated/Fox.glb#Animation1");
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("models/animated/Fox.glb#Scene0"),
main_sphere_material: world.add_asset(Color::from(SILVER)),
main_scene: world
.load_asset("models/IrradianceVolumeExample/IrradianceVolumeExample.glb#Scene0"),
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 {
transform: VOXEL_TRANSFORM.inverse(),
inverse_transform: VOXEL_TRANSFORM,
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
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()
});
}
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,
));
}
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
fn spawn_reflection_probe(commands: &mut Commands, cubemaps: &Cubemaps) {
commands.spawn(ReflectionProbeBundle {
spatial: SpatialBundle {
// 2.0 because the sphere's radius is 1.0 and we want to fully enclose it.
transform: Transform::from_scale(Vec3::splat(2.0)),
..SpatialBundle::default()
},
light_probe: LightProbe,
environment_map: EnvironmentMapLight {
diffuse_map: cubemaps.diffuse.clone(),
specular_map: cubemaps.specular_reflection_probe.clone(),
intensity: 5000.0,
},
});
}
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<CustomMaterial>>,
asset_server: Res<AssetServer>,
) {
// camera
commands.spawn(Camera2dBundle::default());
// quad
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Rectangle::default()).into(),
transform: Transform::default().with_scale(Vec3::splat(128.)),
material: materials.add(CustomMaterial {
color: LinearRgba::BLUE,
color_texture: Some(asset_server.load("branding/icon.png")),
}),
..default()
});
}
- examples/ecs/parallel_query.rs
- examples/stress_tests/bevymark.rs
- examples/2d/sprite_sheet.rs
- examples/shader/compute_shader_game_of_life.rs
- examples/animation/animation_graph.rs
- examples/transforms/transform.rs
- examples/3d/atmospheric_fog.rs
- examples/stress_tests/many_sprites.rs
- examples/ecs/hierarchy.rs
- examples/2d/mesh2d_vertex_color_texture.rs
- examples/gizmos/3d_gizmos.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/3d/motion_blur.rs
- examples/3d/spherical_area_lights.rs
- examples/3d/fog.rs
- examples/2d/sprite_animation.rs
- examples/stress_tests/many_lights.rs
- examples/ecs/iter_combinations.rs
- examples/3d/meshlet.rs
- examples/stress_tests/many_foxes.rs
- examples/2d/texture_atlas.rs
- examples/3d/deferred_rendering.rs
- examples/stress_tests/many_cubes.rs
- examples/animation/animated_transform.rs
- examples/3d/transmission.rs
sourcepub fn select(mask: BVec3, if_true: Vec3, if_false: Vec3) -> Vec3
pub fn select(mask: BVec3, if_true: Vec3, if_false: Vec3) -> Vec3
Creates a vector from the elements in if_true
and if_false
, selecting which to use
for each element of self
.
A true element in the mask uses the corresponding element from if_true
, and false
uses the element from if_false
.
sourcepub const fn from_array(a: [f32; 3]) -> Vec3
pub const fn from_array(a: [f32; 3]) -> Vec3
Creates a new vector from an array.
sourcepub const fn from_slice(slice: &[f32]) -> Vec3
pub const fn from_slice(slice: &[f32]) -> Vec3
Creates a vector from the first 3 values in slice
.
§Panics
Panics if slice
is less than 3 elements long.
sourcepub fn write_to_slice(self, slice: &mut [f32])
pub fn write_to_slice(self, slice: &mut [f32])
Writes the elements of self
to the first 3 elements in slice
.
§Panics
Panics if slice
is less than 3 elements long.
sourcepub fn truncate(self) -> Vec2
pub fn truncate(self) -> Vec2
Creates a 2D vector from the x
and y
elements of self
, discarding z
.
Truncation may also be performed by using self.xy()
.
Examples found in repository?
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);
}
}
More examples
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;
}
}
}
}
sourcepub fn dot_into_vec(self, rhs: Vec3) -> Vec3
pub fn dot_into_vec(self, rhs: Vec3) -> Vec3
Returns a vector where every component is the dot product of self
and rhs
.
sourcepub fn min(self, rhs: Vec3) -> Vec3
pub fn min(self, rhs: Vec3) -> Vec3
Returns a vector containing the minimum values for each element of self
and rhs
.
In other words this computes [self.x.min(rhs.x), self.y.min(rhs.y), ..]
.
Examples found in repository?
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);
}
sourcepub fn max(self, rhs: Vec3) -> Vec3
pub fn max(self, rhs: Vec3) -> Vec3
Returns a vector containing the maximum values for each element of self
and rhs
.
In other words this computes [self.x.max(rhs.x), self.y.max(rhs.y), ..]
.
Examples found in repository?
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);
}
sourcepub fn clamp(self, min: Vec3, max: Vec3) -> Vec3
pub fn clamp(self, min: Vec3, max: Vec3) -> Vec3
Component-wise clamping of values, similar to f32::clamp
.
Each element in min
must be less-or-equal to the corresponding element in max
.
§Panics
Will panic if min
is greater than max
when glam_assert
is enabled.
sourcepub fn min_element(self) -> f32
pub fn min_element(self) -> f32
Returns the horizontal minimum of self
.
In other words this computes min(x, y, ..)
.
Examples found in repository?
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();
}
}
}
sourcepub fn max_element(self) -> f32
pub fn max_element(self) -> f32
Returns the horizontal maximum of self
.
In other words this computes max(x, y, ..)
.
Examples found in repository?
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();
}
}
}
sourcepub fn cmpeq(self, rhs: Vec3) -> BVec3
pub fn cmpeq(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a ==
comparison for each element of
self
and rhs
.
In other words, this computes [self.x == rhs.x, self.y == rhs.y, ..]
for all
elements.
sourcepub fn cmpne(self, rhs: Vec3) -> BVec3
pub fn cmpne(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a !=
comparison for each element of
self
and rhs
.
In other words this computes [self.x != rhs.x, self.y != rhs.y, ..]
for all
elements.
sourcepub fn cmpge(self, rhs: Vec3) -> BVec3
pub fn cmpge(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a >=
comparison for each element of
self
and rhs
.
In other words this computes [self.x >= rhs.x, self.y >= rhs.y, ..]
for all
elements.
sourcepub fn cmpgt(self, rhs: Vec3) -> BVec3
pub fn cmpgt(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a >
comparison for each element of
self
and rhs
.
In other words this computes [self.x > rhs.x, self.y > rhs.y, ..]
for all
elements.
sourcepub fn cmple(self, rhs: Vec3) -> BVec3
pub fn cmple(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a <=
comparison for each element of
self
and rhs
.
In other words this computes [self.x <= rhs.x, self.y <= rhs.y, ..]
for all
elements.
sourcepub fn cmplt(self, rhs: Vec3) -> BVec3
pub fn cmplt(self, rhs: Vec3) -> BVec3
Returns a vector mask containing the result of a <
comparison for each element of
self
and rhs
.
In other words this computes [self.x < rhs.x, self.y < rhs.y, ..]
for all
elements.
sourcepub fn abs(self) -> Vec3
pub fn abs(self) -> Vec3
Returns a vector containing the absolute value of each element of self
.
sourcepub fn signum(self) -> Vec3
pub fn signum(self) -> Vec3
Returns a vector with elements representing the sign of self
.
1.0
if the number is positive,+0.0
orINFINITY
-1.0
if the number is negative,-0.0
orNEG_INFINITY
NAN
if the number isNAN
sourcepub fn copysign(self, rhs: Vec3) -> Vec3
pub fn copysign(self, rhs: Vec3) -> Vec3
Returns a vector with signs of rhs
and the magnitudes of self
.
sourcepub fn is_negative_bitmask(self) -> u32
pub fn is_negative_bitmask(self) -> u32
Returns a bitmask with the lowest 3 bits set to the sign bits from the elements of self
.
A negative element results in a 1
bit and a positive element in a 0
bit. Element x
goes
into the first lowest bit, element y
into the second, etc.
sourcepub fn is_finite(self) -> bool
pub fn is_finite(self) -> bool
Returns true
if, and only if, all elements are finite. If any element is either
NaN
, positive or negative infinity, this will return false
.
sourcepub fn is_nan_mask(self) -> BVec3
pub fn is_nan_mask(self) -> BVec3
Performs is_nan
on each element of self, returning a vector mask of the results.
In other words, this computes [x.is_nan(), y.is_nan(), z.is_nan(), w.is_nan()]
.
sourcepub fn length(self) -> f32
pub fn length(self) -> f32
Computes the length of self
.
Examples found in repository?
More examples
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
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);
}
}
}
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);
}
}
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
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);
}
}
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
fn example_control_system(
mut commands: Commands,
mut materials: ResMut<Assets<StandardMaterial>>,
controllable: Query<(&Handle<StandardMaterial>, &ExampleControls)>,
mut camera: Query<
(
Entity,
&mut Camera,
&mut Camera3d,
&mut Transform,
Option<&DepthPrepass>,
Option<&TemporalJitter>,
),
With<Camera3d>,
>,
mut display: Query<&mut Text, With<ExampleDisplay>>,
mut state: Local<ExampleState>,
time: Res<Time>,
input: Res<ButtonInput<KeyCode>>,
) {
if input.pressed(KeyCode::Digit2) {
state.diffuse_transmission = (state.diffuse_transmission + time.delta_seconds()).min(1.0);
} else if input.pressed(KeyCode::Digit1) {
state.diffuse_transmission = (state.diffuse_transmission - time.delta_seconds()).max(0.0);
}
if input.pressed(KeyCode::KeyW) {
state.specular_transmission = (state.specular_transmission + time.delta_seconds()).min(1.0);
} else if input.pressed(KeyCode::KeyQ) {
state.specular_transmission = (state.specular_transmission - time.delta_seconds()).max(0.0);
}
if input.pressed(KeyCode::KeyS) {
state.thickness = (state.thickness + time.delta_seconds()).min(5.0);
} else if input.pressed(KeyCode::KeyA) {
state.thickness = (state.thickness - time.delta_seconds()).max(0.0);
}
if input.pressed(KeyCode::KeyX) {
state.ior = (state.ior + time.delta_seconds()).min(3.0);
} else if input.pressed(KeyCode::KeyZ) {
state.ior = (state.ior - time.delta_seconds()).max(1.0);
}
if input.pressed(KeyCode::KeyI) {
state.reflectance = (state.reflectance + time.delta_seconds()).min(1.0);
} else if input.pressed(KeyCode::KeyU) {
state.reflectance = (state.reflectance - time.delta_seconds()).max(0.0);
}
if input.pressed(KeyCode::KeyR) {
state.perceptual_roughness = (state.perceptual_roughness + time.delta_seconds()).min(1.0);
} else if input.pressed(KeyCode::KeyE) {
state.perceptual_roughness = (state.perceptual_roughness - time.delta_seconds()).max(0.0);
}
let randomize_colors = input.just_pressed(KeyCode::KeyC);
for (material_handle, controls) in &controllable {
let material = materials.get_mut(material_handle).unwrap();
if controls.specular_transmission {
material.specular_transmission = state.specular_transmission;
material.thickness = state.thickness;
material.ior = state.ior;
material.perceptual_roughness = state.perceptual_roughness;
material.reflectance = state.reflectance;
}
if controls.diffuse_transmission {
material.diffuse_transmission = state.diffuse_transmission;
}
if controls.color && randomize_colors {
material.base_color =
Color::srgba(random(), random(), random(), material.base_color.alpha());
}
}
let (
camera_entity,
mut camera,
mut camera_3d,
mut camera_transform,
depth_prepass,
temporal_jitter,
) = camera.single_mut();
if input.just_pressed(KeyCode::KeyH) {
camera.hdr = !camera.hdr;
}
#[cfg(not(all(feature = "webgl2", target_arch = "wasm32")))]
if input.just_pressed(KeyCode::KeyD) {
if depth_prepass.is_none() {
commands.entity(camera_entity).insert(DepthPrepass);
} else {
commands.entity(camera_entity).remove::<DepthPrepass>();
}
}
#[cfg(not(all(feature = "webgl2", target_arch = "wasm32")))]
if input.just_pressed(KeyCode::KeyT) {
if temporal_jitter.is_none() {
commands.entity(camera_entity).insert((
TemporalJitter::default(),
TemporalAntiAliasSettings::default(),
));
} else {
commands
.entity(camera_entity)
.remove::<(TemporalJitter, TemporalAntiAliasSettings)>();
}
}
if input.just_pressed(KeyCode::KeyO) && camera_3d.screen_space_specular_transmission_steps > 0 {
camera_3d.screen_space_specular_transmission_steps -= 1;
}
if input.just_pressed(KeyCode::KeyP) && camera_3d.screen_space_specular_transmission_steps < 4 {
camera_3d.screen_space_specular_transmission_steps += 1;
}
if input.just_pressed(KeyCode::KeyJ) {
camera_3d.screen_space_specular_transmission_quality = ScreenSpaceTransmissionQuality::Low;
}
if input.just_pressed(KeyCode::KeyK) {
camera_3d.screen_space_specular_transmission_quality =
ScreenSpaceTransmissionQuality::Medium;
}
if input.just_pressed(KeyCode::KeyL) {
camera_3d.screen_space_specular_transmission_quality = ScreenSpaceTransmissionQuality::High;
}
if input.just_pressed(KeyCode::Semicolon) {
camera_3d.screen_space_specular_transmission_quality =
ScreenSpaceTransmissionQuality::Ultra;
}
let rotation = if input.pressed(KeyCode::ArrowRight) {
state.auto_camera = false;
time.delta_seconds()
} else if input.pressed(KeyCode::ArrowLeft) {
state.auto_camera = false;
-time.delta_seconds()
} else if state.auto_camera {
time.delta_seconds() * 0.25
} else {
0.0
};
let distance_change =
if input.pressed(KeyCode::ArrowDown) && camera_transform.translation.length() < 25.0 {
time.delta_seconds()
} else if input.pressed(KeyCode::ArrowUp) && camera_transform.translation.length() > 2.0 {
-time.delta_seconds()
} else {
0.0
};
camera_transform.translation *= distance_change.exp();
camera_transform.rotate_around(
Vec3::ZERO,
Quat::from_euler(EulerRot::XYZ, 0.0, rotation, 0.0),
);
let mut display = display.single_mut();
display.sections[0].value = format!(
concat!(
" J / K / L / ; Screen Space Specular Transmissive Quality: {:?}\n",
" O / P Screen Space Specular Transmissive Steps: {}\n",
" 1 / 2 Diffuse Transmission: {:.2}\n",
" Q / W Specular Transmission: {:.2}\n",
" A / S Thickness: {:.2}\n",
" Z / X IOR: {:.2}\n",
" E / R Perceptual Roughness: {:.2}\n",
" U / I Reflectance: {:.2}\n",
" Arrow Keys Control Camera\n",
" C Randomize Colors\n",
" H HDR + Bloom: {}\n",
" D Depth Prepass: {}\n",
" T TAA: {}\n",
),
camera_3d.screen_space_specular_transmission_quality,
camera_3d.screen_space_specular_transmission_steps,
state.diffuse_transmission,
state.specular_transmission,
state.thickness,
state.ior,
state.perceptual_roughness,
state.reflectance,
if camera.hdr { "ON " } else { "OFF" },
if cfg!(any(not(feature = "webgl2"), not(target_arch = "wasm32"))) {
if depth_prepass.is_some() {
"ON "
} else {
"OFF"
}
} else {
"N/A (WebGL)"
},
if cfg!(any(not(feature = "webgl2"), not(target_arch = "wasm32"))) {
if temporal_jitter.is_some() {
if depth_prepass.is_some() {
"ON "
} else {
"N/A (Needs Depth Prepass)"
}
} else {
"OFF"
}
} else {
"N/A (WebGL)"
},
);
}
sourcepub fn length_squared(self) -> f32
pub fn length_squared(self) -> f32
Computes the squared length of self
.
This is faster than length()
as it avoids a square root operation.
Examples found in repository?
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
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);
}
}
}
sourcepub fn length_recip(self) -> f32
pub fn length_recip(self) -> f32
Computes 1.0 / length()
.
For valid results, self
must not be of length zero.
sourcepub fn distance(self, rhs: Vec3) -> f32
pub fn distance(self, rhs: Vec3) -> f32
Computes the Euclidean distance between two points in space.
sourcepub fn distance_squared(self, rhs: Vec3) -> f32
pub fn distance_squared(self, rhs: Vec3) -> f32
Compute the squared euclidean distance between two points in space.
sourcepub fn div_euclid(self, rhs: Vec3) -> Vec3
pub fn div_euclid(self, rhs: Vec3) -> Vec3
Returns the element-wise quotient of [Euclidean division] of self
by rhs
.
sourcepub fn rem_euclid(self, rhs: Vec3) -> Vec3
pub fn rem_euclid(self, rhs: Vec3) -> Vec3
Returns the element-wise remainder of Euclidean division of self
by rhs
.
sourcepub fn normalize(self) -> Vec3
pub fn normalize(self) -> Vec3
Returns self
normalized to length 1.0.
For valid results, self
must 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?
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();
}
}
}
More examples
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
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,
);
}
}
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
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,
);
my_gizmos.sphere(Vec3::new(1., 0.5, 0.), Quat::IDENTITY, 0.5, RED);
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,
)
.segments(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)
.segments(64);
my_gizmos
.sphere(Vec3::ZERO, Quat::IDENTITY, 3.2, BLACK)
.circle_segments(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);
}
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
fn generate_bodies(
time: Res<Time<Fixed>>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let mesh = meshes.add(Sphere::new(1.0).mesh().ico(3).unwrap());
let color_range = 0.5..1.0;
let vel_range = -0.5..0.5;
// We're seeding the PRNG here to make this example deterministic for testing purposes.
// This isn't strictly required in practical use unless you need your app to be deterministic.
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
for _ in 0..NUM_BODIES {
let radius: f32 = rng.gen_range(0.1..0.7);
let mass_value = radius.powi(3) * 10.;
let position = Vec3::new(
rng.gen_range(-1.0..1.0),
rng.gen_range(-1.0..1.0),
rng.gen_range(-1.0..1.0),
)
.normalize()
* rng.gen_range(0.2f32..1.0).cbrt()
* 15.;
commands.spawn(BodyBundle {
pbr: PbrBundle {
transform: Transform {
translation: position,
scale: Vec3::splat(radius),
..default()
},
mesh: mesh.clone(),
material: materials.add(Color::srgb(
rng.gen_range(color_range.clone()),
rng.gen_range(color_range.clone()),
rng.gen_range(color_range.clone()),
)),
..default()
},
mass: Mass(mass_value),
acceleration: Acceleration(Vec3::ZERO),
last_pos: LastPos(
position
- Vec3::new(
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
) * time.timestep().as_secs_f32(),
),
});
}
// add bigger "star" body in the center
let star_radius = 1.;
commands
.spawn((
BodyBundle {
pbr: PbrBundle {
transform: Transform::from_scale(Vec3::splat(star_radius)),
mesh: meshes.add(Sphere::new(1.0).mesh().ico(5).unwrap()),
material: materials.add(StandardMaterial {
base_color: ORANGE_RED.into(),
emissive: (LinearRgba::from(ORANGE_RED) * 18.).into(),
..default()
}),
..default()
},
mass: Mass(500.0),
..default()
},
Star,
))
.with_children(|p| {
p.spawn(PointLightBundle {
point_light: PointLight {
color: Color::WHITE,
range: 100.0,
radius: star_radius,
..default()
},
..default()
});
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 10.5, -30.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
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);
}
}
}
sourcepub fn try_normalize(self) -> Option<Vec3>
pub fn try_normalize(self) -> Option<Vec3>
Returns self
normalized to length 1.0 if possible, else returns None
.
In particular, if the input is zero (or very close to zero), or non-finite,
the result of this operation will be None
.
See also Self::normalize_or_zero()
.
Examples found in repository?
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
fn rotate_primitive_3d_meshes(
mut primitives_3d: Query<
(&mut Transform, &ViewVisibility),
(With<PrimitiveData>, With<MeshDim3>),
>,
time: Res<Time>,
) {
let rotation_3d = Quat::from_rotation_arc(
Vec3::Z,
Vec3::new(
time.elapsed_seconds().sin(),
time.elapsed_seconds().cos(),
time.elapsed_seconds().sin() * 0.5,
)
.try_normalize()
.unwrap_or(Vec3::Z),
);
primitives_3d
.iter_mut()
.filter(|(_, vis)| vis.get())
.for_each(|(mut transform, _)| {
transform.rotation = rotation_3d;
});
}
fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
let rotation = Quat::from_rotation_arc(
Vec3::Z,
Vec3::new(
time.elapsed_seconds().sin(),
time.elapsed_seconds().cos(),
time.elapsed_seconds().sin() * 0.5,
)
.try_normalize()
.unwrap_or(Vec3::Z),
);
let color = Color::WHITE;
let segments = 10;
match state.get() {
PrimitiveSelected::RectangleAndCuboid => {
gizmos.primitive_3d(CUBOID, POSITION, rotation, color);
}
PrimitiveSelected::CircleAndSphere => drop(
gizmos
.primitive_3d(SPHERE, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Ellipse => {}
PrimitiveSelected::Triangle => {}
PrimitiveSelected::Plane => drop(gizmos.primitive_3d(PLANE_3D, POSITION, rotation, color)),
PrimitiveSelected::Line => gizmos.primitive_3d(LINE3D, POSITION, rotation, color),
PrimitiveSelected::Segment => gizmos.primitive_3d(SEGMENT_3D, POSITION, rotation, color),
PrimitiveSelected::Polyline => gizmos.primitive_3d(POLYLINE_3D, POSITION, rotation, color),
PrimitiveSelected::Polygon => {}
PrimitiveSelected::RegularPolygon => {}
PrimitiveSelected::Capsule => drop(
gizmos
.primitive_3d(CAPSULE_3D, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Cylinder => drop(
gizmos
.primitive_3d(CYLINDER, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::Cone => drop(
gizmos
.primitive_3d(CONE, POSITION, rotation, color)
.segments(segments),
),
PrimitiveSelected::ConicalFrustum => {
gizmos.primitive_3d(CONICAL_FRUSTUM, POSITION, rotation, color);
}
PrimitiveSelected::Torus => drop(
gizmos
.primitive_3d(TORUS, POSITION, rotation, color)
.minor_segments(segments)
.major_segments(segments),
),
}
}
sourcepub fn normalize_or_zero(self) -> Vec3
pub fn normalize_or_zero(self) -> Vec3
Returns self
normalized to length 1.0 if possible, else returns zero.
In particular, if the input is zero (or very close to zero), or non-finite, the result of this operation will be zero.
See also Self::try_normalize()
.
sourcepub fn is_normalized(self) -> bool
pub fn is_normalized(self) -> bool
Returns whether self
is length 1.0
or not.
Uses a precision threshold of 1e-6
.
sourcepub fn project_onto(self, rhs: Vec3) -> Vec3
pub fn project_onto(self, rhs: Vec3) -> Vec3
Returns the vector projection of self
onto rhs
.
rhs
must be of non-zero length.
§Panics
Will panic if rhs
is zero length when glam_assert
is enabled.
sourcepub fn reject_from(self, rhs: Vec3) -> Vec3
pub fn reject_from(self, rhs: Vec3) -> Vec3
Returns the vector rejection of self
from rhs
.
The vector rejection is the vector perpendicular to the projection of self
onto
rhs
, in rhs words the result of self - self.project_onto(rhs)
.
rhs
must be of non-zero length.
§Panics
Will panic if rhs
has a length of zero when glam_assert
is enabled.
sourcepub fn project_onto_normalized(self, rhs: Vec3) -> Vec3
pub fn project_onto_normalized(self, rhs: Vec3) -> Vec3
Returns the vector projection of self
onto rhs
.
rhs
must be normalized.
§Panics
Will panic if rhs
is not normalized when glam_assert
is enabled.
sourcepub fn reject_from_normalized(self, rhs: Vec3) -> Vec3
pub fn reject_from_normalized(self, rhs: Vec3) -> Vec3
Returns the vector rejection of self
from rhs
.
The vector rejection is the vector perpendicular to the projection of self
onto
rhs
, in rhs words the result of self - self.project_onto(rhs)
.
rhs
must be normalized.
§Panics
Will panic if rhs
is not normalized when glam_assert
is enabled.
sourcepub fn round(self) -> Vec3
pub fn round(self) -> Vec3
Returns a vector containing the nearest integer to a number for each element of self
.
Round half-way cases away from 0.0.
sourcepub fn floor(self) -> Vec3
pub fn floor(self) -> Vec3
Returns a vector containing the largest integer less than or equal to a number for each
element of self
.
Examples found in repository?
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();
}
}
}
sourcepub fn ceil(self) -> Vec3
pub fn ceil(self) -> Vec3
Returns a vector containing the smallest integer greater than or equal to a number for
each element of self
.
Examples found in repository?
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();
}
}
}
sourcepub fn trunc(self) -> Vec3
pub fn trunc(self) -> Vec3
Returns a vector containing the integer part each element of self
. This means numbers are
always truncated towards zero.
sourcepub fn fract(self) -> Vec3
pub fn fract(self) -> Vec3
Returns a vector containing the fractional part of the vector, e.g. self - self.floor()
.
Note that this is fast but not precise for large numbers.
sourcepub fn exp(self) -> Vec3
pub fn exp(self) -> Vec3
Returns a vector containing e^self
(the exponential function) for each element of
self
.
sourcepub fn powf(self, n: f32) -> Vec3
pub fn powf(self, n: f32) -> Vec3
Returns a vector containing each element of self
raised to the power of n
.
sourcepub fn recip(self) -> Vec3
pub fn recip(self) -> Vec3
Returns a vector containing the reciprocal 1.0/n
of each element of self
.
sourcepub fn lerp(self, rhs: Vec3, s: f32) -> Vec3
pub fn lerp(self, rhs: Vec3, s: f32) -> Vec3
Performs a linear interpolation between self
and rhs
based on the value s
.
When s
is 0.0
, the result will be equal to self
. When s
is 1.0
, the result
will be equal to rhs
. When s
is outside of range [0, 1]
, the result is linearly
extrapolated.
Examples found in repository?
More examples
185 186 187 188 189 190 191 192 193 194 195 196 197
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);
}
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
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);
}
}
sourcepub fn abs_diff_eq(self, rhs: Vec3, max_abs_diff: f32) -> bool
pub fn abs_diff_eq(self, rhs: Vec3, max_abs_diff: f32) -> bool
Returns true if the absolute difference of all elements between self
and rhs
is
less than or equal to max_abs_diff
.
This can be used to compare if two vectors contain similar elements. It works best when
comparing with a known value. The max_abs_diff
that should be used used depends on
the values being compared against.
For more see comparing floating point numbers.
sourcepub fn clamp_length(self, min: f32, max: f32) -> Vec3
pub fn clamp_length(self, min: f32, max: f32) -> Vec3
Returns a vector with a length no less than min
and no more than max
§Panics
Will panic if min
is greater than max
when glam_assert
is enabled.
sourcepub fn clamp_length_max(self, max: f32) -> Vec3
pub fn clamp_length_max(self, max: f32) -> Vec3
Returns a vector with a length no more than max
sourcepub fn clamp_length_min(self, min: f32) -> Vec3
pub fn clamp_length_min(self, min: f32) -> Vec3
Returns a vector with a length no less than min
sourcepub fn mul_add(self, a: Vec3, b: Vec3) -> Vec3
pub fn mul_add(self, a: Vec3, b: Vec3) -> Vec3
Fused multiply-add. Computes (self * a) + b
element-wise with only one rounding
error, yielding a more accurate result than an unfused multiply-add.
Using mul_add
may be more performant than an unfused multiply-add if the target
architecture has a dedicated fma CPU instruction. However, this is not always true,
and will be heavily dependant on designing algorithms with specific target hardware in
mind.
sourcepub fn angle_between(self, rhs: Vec3) -> f32
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.
sourcepub fn any_orthogonal_vector(&self) -> Vec3
pub fn any_orthogonal_vector(&self) -> Vec3
Returns some vector that is orthogonal to the given one.
The input vector must be finite and non-zero.
The output vector is not necessarily unit length. For that use
Self::any_orthonormal_vector()
instead.
sourcepub fn any_orthonormal_vector(&self) -> Vec3
pub fn any_orthonormal_vector(&self) -> Vec3
Returns any unit vector that is orthogonal to the given one.
The input vector must be unit length.
§Panics
Will panic if self
is not normalized when glam_assert
is enabled.
sourcepub fn any_orthonormal_pair(&self) -> (Vec3, Vec3)
pub fn any_orthonormal_pair(&self) -> (Vec3, Vec3)
Given a unit vector return two other vectors that together form an orthonormal basis. That is, all three vectors are orthogonal to each other and are normalized.
§Panics
Will panic if self
is not normalized when glam_assert
is enabled.
sourcepub fn as_i16vec3(&self) -> I16Vec3
pub fn as_i16vec3(&self) -> I16Vec3
Casts all elements of self
to i16
.
sourcepub fn as_u16vec3(&self) -> U16Vec3
pub fn as_u16vec3(&self) -> U16Vec3
Casts all elements of self
to u16
.
sourcepub fn as_i64vec3(&self) -> I64Vec3
pub fn as_i64vec3(&self) -> I64Vec3
Casts all elements of self
to i64
.
sourcepub fn as_u64vec3(&self) -> U64Vec3
pub fn as_u64vec3(&self) -> U64Vec3
Casts all elements of self
to u64
.
Trait Implementations§
source§impl AddAssign<f32> for Vec3
impl AddAssign<f32> for Vec3
source§fn add_assign(&mut self, rhs: f32)
fn add_assign(&mut self, rhs: f32)
+=
operation. Read moresource§impl AddAssign for Vec3
impl AddAssign for Vec3
source§fn add_assign(&mut self, rhs: Vec3)
fn add_assign(&mut self, rhs: Vec3)
+=
operation. Read more§impl Animatable for Vec3
impl Animatable for Vec3
§fn blend(inputs: impl Iterator<Item = BlendInput<Vec3>>) -> Vec3
fn blend(inputs: impl Iterator<Item = BlendInput<Vec3>>) -> Vec3
§fn post_process(&mut self, _world: &World)
fn post_process(&mut self, _world: &World)
World
.
Most animatable types do not need to implement this.§impl AsMutVectorParts<f32, 3> for Vec3
impl AsMutVectorParts<f32, 3> for Vec3
fn as_mut_parts(&mut self) -> &mut [f32; 3]
§impl AsRefVectorParts<f32, 3> for Vec3
impl AsRefVectorParts<f32, 3> for Vec3
fn as_ref_parts(&self) -> &[f32; 3]
§impl CreateFrom for Vec3
impl CreateFrom for Vec3
fn create_from<B>(reader: &mut Reader<B>) -> Vec3where
B: BufferRef,
source§impl<'de> Deserialize<'de> for Vec3
impl<'de> Deserialize<'de> for Vec3
source§fn deserialize<D>(
deserializer: D
) -> Result<Vec3, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D
) -> Result<Vec3, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
source§impl DivAssign<f32> for Vec3
impl DivAssign<f32> for Vec3
source§fn div_assign(&mut self, rhs: f32)
fn div_assign(&mut self, rhs: f32)
/=
operation. Read moresource§impl DivAssign for Vec3
impl DivAssign for Vec3
source§fn div_assign(&mut self, rhs: Vec3)
fn div_assign(&mut self, rhs: Vec3)
/=
operation. Read more§impl FromIterator<Vec3> for BoxedPolyline3d
impl FromIterator<Vec3> for BoxedPolyline3d
§fn from_iter<I>(iter: I) -> BoxedPolyline3dwhere
I: IntoIterator<Item = Vec3>,
fn from_iter<I>(iter: I) -> BoxedPolyline3dwhere
I: IntoIterator<Item = Vec3>,
§impl<const N: usize> FromIterator<Vec3> for Polyline3d<N>
impl<const N: usize> FromIterator<Vec3> for Polyline3d<N>
§fn from_iter<I>(iter: I) -> Polyline3d<N>where
I: IntoIterator<Item = Vec3>,
fn from_iter<I>(iter: I) -> Polyline3d<N>where
I: IntoIterator<Item = Vec3>,
§impl FromReflect for Vec3
impl FromReflect for Vec3
§fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<Vec3>
fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<Vec3>
Self
from a reflected value.§fn take_from_reflect(
reflect: Box<dyn Reflect>
) -> Result<Self, Box<dyn Reflect>>
fn take_from_reflect( reflect: Box<dyn Reflect> ) -> Result<Self, Box<dyn Reflect>>
Self
using,
constructing the value using from_reflect
if that fails. Read more§impl FromVectorParts<f32, 3> for Vec3
impl FromVectorParts<f32, 3> for Vec3
fn from_parts(parts: [f32; 3]) -> Vec3
§impl GetTypeRegistration for Vec3
impl GetTypeRegistration for Vec3
§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration
for this type.§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
§impl Mul<Vec3> for GlobalTransform
impl Mul<Vec3> for GlobalTransform
source§impl MulAssign<f32> for Vec3
impl MulAssign<f32> for Vec3
source§fn mul_assign(&mut self, rhs: f32)
fn mul_assign(&mut self, rhs: f32)
*=
operation. Read moresource§impl MulAssign for Vec3
impl MulAssign for Vec3
source§fn mul_assign(&mut self, rhs: Vec3)
fn mul_assign(&mut self, rhs: Vec3)
*=
operation. Read more§impl NormedVectorSpace for Vec3
impl NormedVectorSpace for Vec3
§fn norm_squared(self) -> f32
fn norm_squared(self) -> f32
NormedVectorSpace::norm
.§fn distance(self, rhs: Self) -> f32
fn distance(self, rhs: Self) -> f32
§fn distance_squared(self, rhs: Self) -> f32
fn distance_squared(self, rhs: Self) -> f32
NormedVectorSpace::distance
.source§impl PartialEq for Vec3
impl PartialEq for Vec3
§impl Reflect for Vec3
impl Reflect for Vec3
§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any
.§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
§fn clone_value(&self) -> Box<dyn Reflect>
fn clone_value(&self) -> Box<dyn Reflect>
Reflect
trait object. Read more§fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>
§fn apply(&mut self, value: &(dyn Reflect + 'static))
fn apply(&mut self, value: &(dyn Reflect + 'static))
§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
§fn reflect_owned(self: Box<Vec3>) -> ReflectOwned
fn reflect_owned(self: Box<Vec3>) -> ReflectOwned
§fn reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>
fn reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>
§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
§fn serializable(&self) -> Option<Serializable<'_>>
fn serializable(&self) -> Option<Serializable<'_>>
§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
source§impl RemAssign<f32> for Vec3
impl RemAssign<f32> for Vec3
source§fn rem_assign(&mut self, rhs: f32)
fn rem_assign(&mut self, rhs: f32)
%=
operation. Read moresource§impl RemAssign for Vec3
impl RemAssign for Vec3
source§fn rem_assign(&mut self, rhs: Vec3)
fn rem_assign(&mut self, rhs: Vec3)
%=
operation. Read moresource§impl Serialize for Vec3
impl Serialize for Vec3
source§fn serialize<S>(
&self,
serializer: S
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
§impl ShaderSize for Vec3where
f32: ShaderSize,
impl ShaderSize for Vec3where
f32: ShaderSize,
§const SHADER_SIZE: NonZero<u64> = _
const SHADER_SIZE: NonZero<u64> = _
ShaderType::min_size
)§impl ShaderType for Vec3where
f32: ShaderSize,
impl ShaderType for Vec3where
f32: ShaderSize,
§fn assert_uniform_compat()
fn assert_uniform_compat()
Self
meets the requirements of the
uniform address space restrictions on stored values and the
uniform address space layout constraints Read more§impl Struct for Vec3
impl Struct for Vec3
§fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
name
as a &dyn Reflect
.§fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
name
as a
&mut dyn Reflect
.§fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
index
as a
&dyn Reflect
.§fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
index
as a &mut dyn Reflect
.§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
§fn clone_dynamic(&self) -> DynamicStruct
fn clone_dynamic(&self) -> DynamicStruct
DynamicStruct
.source§impl SubAssign<f32> for Vec3
impl SubAssign<f32> for Vec3
source§fn sub_assign(&mut self, rhs: f32)
fn sub_assign(&mut self, rhs: f32)
-=
operation. Read moresource§impl SubAssign for Vec3
impl SubAssign for Vec3
source§fn sub_assign(&mut self, rhs: Vec3)
fn sub_assign(&mut self, rhs: Vec3)
-=
operation. Read more§impl TypePath for Vec3
impl TypePath for Vec3
§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
source§impl Vec3Swizzles for Vec3
impl Vec3Swizzles for Vec3
type Vec2 = Vec2
type Vec4 = Vec4
fn xx(self) -> Vec2
fn xy(self) -> Vec2
fn xz(self) -> Vec2
fn yx(self) -> Vec2
fn yy(self) -> Vec2
fn yz(self) -> Vec2
fn zx(self) -> Vec2
fn zy(self) -> Vec2
fn zz(self) -> Vec2
fn xxx(self) -> Vec3
fn xxy(self) -> Vec3
fn xxz(self) -> Vec3
fn xyx(self) -> Vec3
fn xyy(self) -> Vec3
fn xyz(self) -> Vec3
fn xzx(self) -> Vec3
fn xzy(self) -> Vec3
fn xzz(self) -> Vec3
fn yxx(self) -> Vec3
fn yxy(self) -> Vec3
fn yxz(self) -> Vec3
fn yyx(self) -> Vec3
fn yyy(self) -> Vec3
fn yyz(self) -> Vec3
fn yzx(self) -> Vec3
fn yzy(self) -> Vec3
fn yzz(self) -> Vec3
fn zxx(self) -> Vec3
fn zxy(self) -> Vec3
fn zxz(self) -> Vec3
fn zyx(self) -> Vec3
fn zyy(self) -> Vec3
fn zyz(self) -> Vec3
fn zzx(self) -> Vec3
fn zzy(self) -> Vec3
fn zzz(self) -> Vec3
fn xxxx(self) -> Vec4
fn xxxy(self) -> Vec4
fn xxxz(self) -> Vec4
fn xxyx(self) -> Vec4
fn xxyy(self) -> Vec4
fn xxyz(self) -> Vec4
fn xxzx(self) -> Vec4
fn xxzy(self) -> Vec4
fn xxzz(self) -> Vec4
fn xyxx(self) -> Vec4
fn xyxy(self) -> Vec4
fn xyxz(self) -> Vec4
fn xyyx(self) -> Vec4
fn xyyy(self) -> Vec4
fn xyyz(self) -> Vec4
fn xyzx(self) -> Vec4
fn xyzy(self) -> Vec4
fn xyzz(self) -> Vec4
fn xzxx(self) -> Vec4
fn xzxy(self) -> Vec4
fn xzxz(self) -> Vec4
fn xzyx(self) -> Vec4
fn xzyy(self) -> Vec4
fn xzyz(self) -> Vec4
fn xzzx(self) -> Vec4
fn xzzy(self) -> Vec4
fn xzzz(self) -> Vec4
fn yxxx(self) -> Vec4
fn yxxy(self) -> Vec4
fn yxxz(self) -> Vec4
fn yxyx(self) -> Vec4
fn yxyy(self) -> Vec4
fn yxyz(self) -> Vec4
fn yxzx(self) -> Vec4
fn yxzy(self) -> Vec4
fn yxzz(self) -> Vec4
fn yyxx(self) -> Vec4
fn yyxy(self) -> Vec4
fn yyxz(self) -> Vec4
fn yyyx(self) -> Vec4
fn yyyy(self) -> Vec4
fn yyyz(self) -> Vec4
fn yyzx(self) -> Vec4
fn yyzy(self) -> Vec4
fn yyzz(self) -> Vec4
fn yzxx(self) -> Vec4
fn yzxy(self) -> Vec4
fn yzxz(self) -> Vec4
fn yzyx(self) -> Vec4
fn yzyy(self) -> Vec4
fn yzyz(self) -> Vec4
fn yzzx(self) -> Vec4
fn yzzy(self) -> Vec4
fn yzzz(self) -> Vec4
fn zxxx(self) -> Vec4
fn zxxy(self) -> Vec4
fn zxxz(self) -> Vec4
fn zxyx(self) -> Vec4
fn zxyy(self) -> Vec4
fn zxyz(self) -> Vec4
fn zxzx(self) -> Vec4
fn zxzy(self) -> Vec4
fn zxzz(self) -> Vec4
fn zyxx(self) -> Vec4
fn zyxy(self) -> Vec4
fn zyxz(self) -> Vec4
fn zyyx(self) -> Vec4
fn zyyy(self) -> Vec4
fn zyyz(self) -> Vec4
fn zyzx(self) -> Vec4
fn zyzy(self) -> Vec4
fn zyzz(self) -> Vec4
fn zzxx(self) -> Vec4
fn zzxy(self) -> Vec4
fn zzxz(self) -> Vec4
fn zzyx(self) -> Vec4
fn zzyy(self) -> Vec4
fn zzyz(self) -> Vec4
fn zzzx(self) -> Vec4
fn zzzy(self) -> Vec4
fn zzzz(self) -> Vec4
§impl VectorSpace for Vec3
impl VectorSpace for Vec3
impl Copy for Vec3
impl Pod for Vec3
impl StructuralPartialEq for Vec3
Auto Trait Implementations§
impl Freeze for Vec3
impl RefUnwindSafe for Vec3
impl Send for Vec3
impl Sync for Vec3
impl Unpin for Vec3
impl UnwindSafe for Vec3
Blanket Implementations§
§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
§type Bits = T
type Bits = T
Self
must have the same layout as the specified Bits
except for
the possible invalid bit patterns being checked during
is_valid_bit_pattern
.§fn is_valid_bit_pattern(_bits: &T) -> bool
fn is_valid_bit_pattern(_bits: &T) -> bool
bits
as &Self
.§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path
.§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident
.§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name
.§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Self
using data from the given World
.§impl<T> GetPath for T
impl<T> GetPath for T
§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>
) -> Result<&(dyn Reflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p> ) -> Result<&(dyn Reflect + 'static), ReflectPathError<'p>>
path
. Read more§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p> ) -> Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>
path
. Read more§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path
. Read more§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path
. Read more§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
§impl<T> NoneValue for Twhere
T: Default,
impl<T> NoneValue for Twhere
T: Default,
type NoneType = T
§fn null_value() -> T
fn null_value() -> T
§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.