Skip to main content

Quat

Struct Quat 

Source
pub struct Quat(/* private fields */);
Expand description

A quaternion representing an orientation.

This quaternion is intended to be of unit length but may denormalize due to floating point “error creep” which can occur when successive quaternion operations are applied.

SIMD vector types are used for storage on supported platforms.

This type is 16 byte aligned.

Implementations§

Source§

impl Quat

Source

pub const IDENTITY: Quat

The identity quaternion. Corresponds to no rotation.

Source

pub const NAN: Quat

All NANs.

Source

pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Quat

Creates a new rotation quaternion.

This should generally not be called manually unless you know what you are doing. Use one of the other constructors instead such as identity or from_axis_angle.

from_xyzw is mostly used by unit tests and serde deserialization.

§Preconditions

This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.

Source

pub const fn from_array(a: [f32; 4]) -> Quat

Creates a rotation quaternion from an array.

§Preconditions

This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.

Source

pub const fn from_vec4(v: Vec4) -> Quat

Creates a new rotation quaternion from a 4D vector.

§Preconditions

This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.

Source

pub fn from_slice(slice: &[f32]) -> Quat

Creates a rotation quaternion from a slice.

§Preconditions

This function does not check if the input is normalized, it is up to the user to provide normalized input or to normalized the resulting quaternion.

§Panics

Panics if slice length is less than 4.

Source

pub fn write_to_slice(self, slice: &mut [f32])

Writes the quaternion to an unaligned slice.

§Panics

Panics if slice length is less than 4.

Source

pub fn from_axis_angle(axis: Vec3, angle: f32) -> Quat

Create a quaternion for a normalized rotation axis and angle (in radians).

The axis must be a unit vector.

§Panics

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

Source

pub fn from_scaled_axis(v: Vec3) -> Quat

Create a quaternion that rotates v.length() radians around v.normalize().

from_scaled_axis(Vec3::ZERO) results in the identity quaternion.

Source

pub fn from_rotation_x(angle: f32) -> Quat

Creates a quaternion from the angle (in radians) around the x axis.

Examples found in repository?
examples/animation.rs (line 530)
527fn orbit_camera(target: Vec3, yaw: f32, pitch: f32) -> Camera {
528    let look_at = target + Vec3::Y * CAMERA_LOOK_HEIGHT;
529    let base = Vec3::new(0.0, CAMERA_UP, CAMERA_BACK);
530    let offset = Quat::from_rotation_y(yaw) * (Quat::from_rotation_x(pitch) * base);
531    Camera::new(
532        View::look_at(look_at + offset, look_at),
533        Projection::perspective(CAMERA_FOV),
534    )
535}
Source

pub fn from_rotation_y(angle: f32) -> Quat

Creates a quaternion from the angle (in radians) around the y axis.

Examples found in repository?
examples/sprite-adventure.rs (line 1323)
1319    fn draw_crates(&self, ctx: &mut FrameContext<'_, Keep>) {
1320        for &(x, z, turn) in &CRATE_POSITIONS {
1321            ctx.draw(Crate.at(Transform::from_scale_rotation_translation(
1322                Vec3::splat(CRATE_SIZE),
1323                Quat::from_rotation_y(turn),
1324                Vec3::new(x, CRATE_SIZE * 0.5, z),
1325            )));
1326        }
1327    }
1328
1329    /// The well: its rim in grey masonry, and the mouth cell laid over the
1330    /// rim's top face.
1331    fn draw_well(&self, ctx: &mut FrameContext<'_, Keep>) {
1332        let cells = Sheet::new(UVec2::new(WELL_CELLS, 1));
1333        ctx.draw(
1334            Well.at(Transform::from_scale_rotation_translation(
1335                WELL_SIZE,
1336                Quat::IDENTITY,
1337                WELL_POSITION + Vec3::Y * (WELL_SIZE.y * 0.5),
1338            ))
1339            .frame(cells.cell(WELL_RIM_CELL)),
1340        );
1341        ctx.draw(
1342            WellMouth
1343                .at(Transform::from_scale_rotation_translation(
1344                    Vec3::new(WELL_SIZE.x, 1.0, WELL_SIZE.z),
1345                    Quat::IDENTITY,
1346                    WELL_POSITION + Vec3::Y * (WELL_SIZE.y + WELL_MOUTH_LIFT),
1347                ))
1348                .frame(cells.cell(WELL_MOUTH_CELL)),
1349        );
1350    }
1351
1352    fn draw_flora(&self, ctx: &mut FrameContext<'_, Keep>) {
1353        for &(x, z, rock) in &FLORA {
1354            let (width, height) = if rock {
1355                (ROCK_WIDTH, ROCK_HEIGHT)
1356            } else {
1357                (BUSH_WIDTH, BUSH_HEIGHT)
1358            };
1359            let standing = Transform::from_scale_rotation_translation(
1360                Vec3::new(width, height, width),
1361                Quat::IDENTITY,
1362                Vec3::new(x, height * 0.5, z),
1363            );
1364            let flora: Instance<Shape, _> = if rock {
1365                Rock.at(standing).into_set()
1366            } else {
1367                Bush.at(standing).into_set()
1368            };
1369            ctx.draw(flora.upright());
1370        }
1371    }
1372
1373    /// One stone box drawn on the ground at `at`, `size` across, sampling
1374    /// the part of the sheet `frame` covers.
1375    fn draw_stone(ctx: &mut FrameContext<'_, Keep>, at: Vec3, size: Vec3, frame: Frame) {
1376        ctx.draw(
1377            Stone
1378                .at(Transform::from_scale_rotation_translation(
1379                    size,
1380                    Quat::IDENTITY,
1381                    at + Vec3::Y * (size.y * 0.5),
1382                ))
1383                .frame(frame),
1384        );
1385    }
1386
1387    /// Two stone pillars drawn where `mouth` blocks the player, each a
1388    /// capital over its own course of masonry, and, on the one the camera
1389    /// looks into, the lintel across their tops and the dark filling
1390    /// the opening under it.
1391    fn draw_mouth(ctx: &mut FrameContext<'_, Keep>, mouth: Mouth) {
1392        for at in mouth.pillars() {
1393            Self::draw_stone(ctx, at, MOUTH_PILLAR_SIZE, Frame::default());
1394        }
1395        if !mouth.looked_into() {
1396            return;
1397        }
1398
1399        Self::draw_stone(
1400            ctx,
1401            mouth.at + Vec3::Y * MOUTH_PILLAR_SIZE.y,
1402            MOUTH_LINTEL_SIZE,
1403            masonry(MOUTH_LINTEL_TILES),
1404        );
1405        ctx.draw(
1406            Quad.at(Transform::from_scale_rotation_translation(
1407                Vec3::new(MOUTH_PILLAR_OFFSET * 2.0, MOUTH_DARK_HEIGHT, 1.0),
1408                Quat::IDENTITY,
1409                mouth.at + Vec3::Y * (MOUTH_DARK_HEIGHT * 0.5),
1410            ))
1411            .material(Material::color(Color::BLACK)),
1412        );
1413    }
1414
1415    fn draw_cave_floor(&self, ctx: &mut FrameContext<'_, Keep>) {
1416        let half = CAVE_HALF_WIDTH as i32;
1417        let near = CAVE_NEAR_Z as i32;
1418        let far = CAVE_FAR_Z as i32;
1419        for col in -half..=half {
1420            for row in far..=near {
1421                let variant = (col * 13 + row * 7).rem_euclid(CAVE_COLUMNS as i32) as u32;
1422                ctx.draw(
1423                    CaveFloor
1424                        .at(Vec3::new(
1425                            col as f32 * TILE_SIZE,
1426                            0.0,
1427                            row as f32 * TILE_SIZE,
1428                        ))
1429                        .frame(
1430                            Sheet::new(UVec2::new(CAVE_COLUMNS, CAVE_ROWS))
1431                                .cell_at(UVec2::new(variant, CAVE_FLOOR_ROW)),
1432                        ),
1433                );
1434            }
1435        }
1436    }
1437
1438    /// The wall drawn at `at` over the meters `standing`, in courses
1439    /// [`WALL_HEIGHT`] tall from the floor up, each cut to the part of it the
1440    /// span leaves; its faces are picked by `seed` and its stone faded to
1441    /// `fade`, which is `1.0` wherever it is solid.
1442    fn draw_wall(
1443        ctx: &mut FrameContext<'_, Keep>,
1444        at: Vec2,
1445        standing: Range<f32>,
1446        seed: i32,
1447        fade: f32,
1448    ) {
1449        for course in 0..WALL_COURSES {
1450            let base = course as f32 * WALL_HEIGHT;
1451            let low = (standing.start - base).max(0.0);
1452            let high = (standing.end - base).min(WALL_HEIGHT);
1453            if high <= low {
1454                continue;
1455            }
1456
1457            let variant = (seed + course).rem_euclid(CAVE_COLUMNS as i32) as u32;
1458            ctx.draw(
1459                CaveWall
1460                    .at(Transform::from_scale_rotation_translation(
1461                        Vec3::new(TILE_SIZE, high - low, TILE_SIZE),
1462                        Quat::IDENTITY,
1463                        Vec3::new(at.x, base + (low + high) * 0.5, at.y),
1464                    ))
1465                    .frame(cave_wall_face(variant, low..high))
1466                    .faded(fade),
1467            );
1468        }
1469    }
1470
1471    /// The room's two side walls and its back wall, full height, and the low
1472    /// wall closing its near end between the side walls and the mouth. The
1473    /// back wall stops short of the corners the side walls already fill, and
1474    /// the near one leaves the mouth's own tile open.
1475    fn draw_cave_walls(&self, ctx: &mut FrameContext<'_, Keep>) {
1476        let half = CAVE_HALF_WIDTH as i32 + 1;
1477        let near = CAVE_NEAR_Z as i32;
1478        let far = CAVE_FAR_Z as i32;
1479
1480        for row in far..=near {
1481            let z = row as f32 * TILE_SIZE;
1482            let west = Vec2::new(-half as f32 * TILE_SIZE, z);
1483            let east = Vec2::new(half as f32 * TILE_SIZE, z);
1484            Self::draw_wall(ctx, west, 0.0..WALL_TOP, row * 5, SOLID);
1485            Self::draw_wall(ctx, east, 0.0..WALL_TOP, row * 5 + 1, SOLID);
1486        }
1487        for col in (-half + 1)..half {
1488            let x = col as f32 * TILE_SIZE;
1489            let back = Vec2::new(x, far as f32 * TILE_SIZE);
1490            Self::draw_wall(ctx, back, 0.0..WALL_TOP, col * 5 + 2, SOLID);
1491            if col != 0 {
1492                let lip = Vec2::new(x, CAVE_LIP_Z);
1493                Self::draw_wall(ctx, lip, 0.0..CAVE_LIP_HEIGHT, col * 5 + 4, SOLID);
1494            }
1495        }
1496    }
1497
1498    /// The wall the door hangs in, run across the room between the side walls
1499    /// with one tile left open on the room's axis for the doorway and stone
1500    /// filling the column over the door. A player behind the wall is drawn
1501    /// through the stacks between them and the camera, at `seen_through`,
1502    /// faded by `ghost`; the rest of it stays solid, and keeps casting.
1503    fn draw_door_wall(ctx: &mut FrameContext<'_, Keep>, seen_through: Option<f32>, ghost: f32) {
1504        let stone = |x: f32| match seen_through {
1505            Some(at) if (x - at).abs() < GHOST_CORRIDOR_HALF => ghost_alpha(ghost),
1506            _ => SOLID,
1507        };
1508        let half = CAVE_HALF_WIDTH as i32;
1509
1510        for col in (-half..=half).filter(|&col| col != 0) {
1511            let x = col as f32 * TILE_SIZE;
1512            Self::draw_wall(
1513                ctx,
1514                Vec2::new(x, DOOR_Z),
1515                0.0..WALL_TOP,
1516                col * 5 + 3,
1517                stone(x),
1518            );
1519        }
1520        Self::draw_wall(
1521            ctx,
1522            Vec2::new(0.0, DOOR_Z),
1523            DOOR_HEIGHT..WALL_TOP,
1524            3,
1525            stone(0.0),
1526        );
1527    }
1528
1529    /// The two torches: an upright cutout post apiece, the flame's loop
1530    /// burning over its binding, and the light that flame casts.
1531    fn draw_torches(&self, ctx: &mut FrameContext<'_, Keep>) {
1532        let elapsed = self.simulated.as_secs_f32();
1533        let loop_cells = Sheet::new(UVec2::new(FLAME_CELLS, 1));
1534
1535        for (index, &(x, z)) in TORCH_POSITIONS.iter().enumerate() {
1536            let base = Vec3::new(x, 0.0, z);
1537            ctx.draw(
1538                Torch
1539                    .at(Transform::from_scale_rotation_translation(
1540                        Vec3::new(TORCH_SPRITE_WIDTH, TORCH_STAND_HEIGHT, 1.0),
1541                        Quat::IDENTITY,
1542                        base + Vec3::Y * (TORCH_STAND_HEIGHT * 0.5),
1543                    ))
1544                    .upright(),
1545            );
1546
1547            let phase = index as f32 * 2.1;
1548            let flicker = (elapsed * FLAME_FLICKER_SPEED + phase).sin();
1549            let flame_pos =
1550                base + Vec3::Y * (TORCH_STAND_HEIGHT + FLAME_LIFT + flicker * FLAME_BOB);
1551
1552            let light_pos = flame_pos + Vec3::new(0.0, TORCH_LIGHT_LIFT, TORCH_LIGHT_STANDOFF);
1553            ctx.light(Light::point(light_pos, TORCH_LIGHT_COLOR, TORCH_LIGHT_RANGE).shadow());
1554            // The pair burn an even share of the loop apart.
1555            let offset = index as u32 * FLAME_CELLS / TORCH_POSITIONS.len() as u32;
1556            ctx.draw(
1557                Flame
1558                    .at(Transform::from_scale_rotation_translation(
1559                        Vec3::splat(FLAME_SIZE),
1560                        Quat::IDENTITY,
1561                        flame_pos,
1562                    ))
1563                    .billboard()
1564                    .roll(flicker * FLAME_ROLL)
1565                    .frame(loop_cells.cell((elapsed * FLAME_RATE) as u32 + offset)),
1566            );
1567        }
1568    }
1569
1570    /// The door at its hinge — swung back against the wall once opened —
1571    /// drawn through alongside its wall, faded by `ghost`.
1572    fn draw_door(&self, ctx: &mut FrameContext<'_, Keep>, ghost: f32) {
1573        let fade = ghost_alpha(ghost);
1574        let swung = if self.door_opening {
1575            Quat::from_rotation_y(core::f32::consts::FRAC_PI_2)
1576        } else {
1577            Quat::IDENTITY
1578        };
1579
1580        ctx.draw(
1581            Door.at(Transform::from_rotation_translation(swung, DOOR_HINGE))
1582                .material(Material::shaded(DOOR_COLOR, DOOR_LITNESS))
1583                .faded(fade),
1584        );
1585    }
1586
1587    /// The posts and lintel framing the doorway, in a color the stone never
1588    /// is, standing clear of the wall so the opening reads as a door from
1589    /// across the chamber. Glowing of their own while the door is closed and
1590    /// within [`INTERACT_RADIUS`], the cue that it opens.
1591    fn draw_door_frame(&self, ctx: &mut FrameContext<'_, Keep>, ghost: f32) {
1592        let reachable =
1593            !self.door_opening && self.position.distance(INTERACT_POINT) < INTERACT_RADIUS;
1594        let material =
1595            Material::shaded(DOOR_FRAME_COLOR, DOOR_FRAME_LITNESS).emissive(if reachable {
1596                DOOR_FRAME_GLOW
1597            } else {
1598                Color::BLACK
1599            });
1600        let fade = ghost_alpha(ghost);
1601        let z = DOOR_WALL_NEAR_Z + DOOR_FRAME_STANDOFF;
1602        let jamb_height = DOOR_HEIGHT + DOOR_FRAME_THICKNESS;
1603
1604        for side in SIDES {
1605            ctx.draw(
1606                Cube.at(Transform::from_scale_rotation_translation(
1607                    Vec3::new(DOOR_FRAME_THICKNESS, jamb_height, DOOR_FRAME_THICKNESS),
1608                    Quat::IDENTITY,
1609                    Vec3::new(
1610                        side * (DOORWAY_HALF + DOOR_FRAME_THICKNESS * 0.5),
1611                        jamb_height * 0.5,
1612                        z,
1613                    ),
1614                ))
1615                .material(material)
1616                .faded(fade),
1617            );
1618        }
1619        ctx.draw(
1620            Cube.at(Transform::from_scale_rotation_translation(
1621                Vec3::new(
1622                    DOOR_WIDTH + DOOR_FRAME_THICKNESS * 2.0,
1623                    DOOR_FRAME_THICKNESS,
1624                    DOOR_FRAME_THICKNESS,
1625                ),
1626                Quat::IDENTITY,
1627                Vec3::new(0.0, DOOR_HEIGHT + DOOR_FRAME_THICKNESS * 0.5, z),
1628            ))
1629            .material(material)
1630            .faded(fade),
1631        );
1632    }
1633
1634    /// A world prompt over the door: what opens it while the player is
1635    /// within [`INTERACT_RADIUS`] and it is closed, and that it swings while
1636    /// it does; gone once it has swung [`DOOR_SWING_TICKS`]. Laid out and
1637    /// placed like `examples/animation.rs`'s own prompt.
1638    fn draw_door_prompt(&self, ctx: &mut FrameContext<'_, Keep>, camera: Camera) {
1639        let near = self.position.distance(INTERACT_POINT) < INTERACT_RADIUS;
1640        let swinging = self.door_opening && self.swing_ticks < DOOR_SWING_TICKS;
1641        let text = if swinging {
1642            "opening"
1643        } else if near && !self.door_opening {
1644            "e opens the door"
1645        } else {
1646            return;
1647        };
1648
1649        let galley = ctx.text_layout(text, egui::FontId::proportional(DOOR_PROMPT_SIZE));
1650        let point = INTERACT_POINT + Vec3::Y * (DOOR_HEIGHT + DOOR_PROMPT_LIFT);
1651        let window_size = ctx.window_size();
1652        let pixels_per_point = ctx.pixels_per_point();
1653        let Some(pixel) = camera.pixel_of(point, window_size) else {
1654            return;
1655        };
1656
1657        ctx.ui(|ui| {
1658            let painter = ui.painter();
1659            let at = logical(pixel, pixels_per_point);
1660            let ink = galley.mesh_bounds;
1661            let pos = egui::pos2(at.x - ink.center().x, at.y - ink.center().y);
1662            let backdrop = egui::Rect::from_center_size(
1663                at,
1664                ink.size() + egui::Vec2::splat(DOOR_PROMPT_PADDING * 2.0),
1665            );
1666            painter.rect_filled(
1667                backdrop,
1668                DOOR_PROMPT_PADDING,
1669                egui::Color32::from_black_alpha(DOOR_PROMPT_BACKDROP),
1670            );
1671            painter.galley(pos, galley, DOOR_PROMPT_COLOR);
1672        });
1673    }
1674
1675    /// The gem, spinning and bobbing over the chamber's floor, and the light
1676    /// it casts over it.
1677    fn draw_gem(&self, ctx: &mut FrameContext<'_, Keep>) {
1678        let t = self.simulated.as_secs_f32();
1679        let bob = (t * 2.0).sin() * GEM_BOB_HEIGHT;
1680        ctx.light(
1681            Light::point(
1682                GEM_POSITION + Vec3::Y * (bob + GEM_LIGHT_LIFT),
1683                GEM_LIGHT_COLOR,
1684                GEM_LIGHT_RANGE,
1685            )
1686            .shadow(),
1687        );
1688        ctx.draw(
1689            Gem.at(Transform::from_scale_rotation_translation(
1690                Vec3::ONE,
1691                Quat::from_rotation_y(t * GEM_SPIN_SPEED),
1692                GEM_POSITION + Vec3::Y * bob,
1693            ))
1694            .material(Material::shaded(GEM_COLOR, 0.7).emissive(GEM_COLOR.dimmed(1.6))),
1695        );
1696    }
More examples
Hide additional examples
examples/animation.rs (line 530)
527fn orbit_camera(target: Vec3, yaw: f32, pitch: f32) -> Camera {
528    let look_at = target + Vec3::Y * CAMERA_LOOK_HEIGHT;
529    let base = Vec3::new(0.0, CAMERA_UP, CAMERA_BACK);
530    let offset = Quat::from_rotation_y(yaw) * (Quat::from_rotation_x(pitch) * base);
531    Camera::new(
532        View::look_at(look_at + offset, look_at),
533        Projection::perspective(CAMERA_FOV),
534    )
535}
536
537/// The logical point egui paints the physical pixel `pixel` at.
538fn logical(pixel: Vec2, pixels_per_point: f32) -> egui::Pos2 {
539    let point = pixel / pixels_per_point;
540    egui::pos2(point.x, point.y)
541}
542
543#[derive(InputButtonAction, Clone, Copy)]
544enum Button {
545    Run,
546    Attack,
547    Jump,
548    Dance,
549    Interact,
550    Restart,
551    Hold,
552    Release,
553}
554
555impl InputButtonAction for Button {
556    fn bindings(&self) -> Vec<ButtonBinding> {
557        match self {
558            Button::Run => vec![Key::LeftShift.into()],
559            Button::Attack => vec![Key::F.into()],
560            Button::Jump => vec![Key::Space.into()],
561            Button::Dance => vec![Key::N.into()],
562            Button::Interact => vec![Key::E.into()],
563            Button::Restart => vec![Key::R.into()],
564            Button::Hold => vec![MouseButton::Left.into()],
565            Button::Release => vec![Key::Escape.into()],
566        }
567    }
568}
569
570/// The camera's own controls: turned and tilted by how far the pointer
571/// moves sideways and upward each tick.
572#[derive(InputAxisAction, Clone, Copy)]
573enum Axis {
574    CameraYaw,
575    CameraPitch,
576}
577
578impl InputAxisAction for Axis {
579    fn bindings(&self) -> Vec<AxisBinding> {
580        match self {
581            Axis::CameraYaw => {
582                vec![AxisBinding::pointer_delta(PointerDelta::Sideways).scale(CAMERA_YAW_SCALE)]
583            }
584            Axis::CameraPitch => {
585                vec![AxisBinding::pointer_delta(PointerDelta::Up).scale(CAMERA_PITCH_SCALE)]
586            }
587        }
588    }
589}
590
591#[derive(InputAxis2Action, Clone, Copy)]
592enum Move {
593    Walk,
594}
595
596impl InputAxis2Action for Move {
597    fn bindings(&self) -> Vec<Axis2Binding> {
598        match self {
599            Move::Walk => vec![
600                Axis2Binding::from(ButtonAxis2 {
601                    left: Key::A,
602                    right: Key::D,
603                    down: Key::S,
604                    up: Key::W,
605                }),
606                Axis2Binding::from(ButtonAxis2 {
607                    left: Key::Left,
608                    right: Key::Right,
609                    down: Key::Down,
610                    up: Key::Up,
611                }),
612            ],
613        }
614    }
615}
616
617struct Controls;
618
619impl InputActions for Controls {
620    type Button = Button;
621    type Axis = Axis;
622    type Axis2 = Move;
623}
624
625/// `text` in [`PANEL_TEXT_COLOR`].
626fn panel_text(text: impl Into<String>) -> egui::RichText {
627    egui::RichText::new(text.into()).color(PANEL_TEXT_COLOR)
628}
629
630struct Scene {
631    elf_pos: Vec3,
632    elf_prev: Vec3,
633    elf_yaw: f32,
634    /// Height the elf is lifted over the ground while off the ground,
635    /// integrated in [`Game::tick`] from [`Self::jump_speed`].
636    elf_height: f32,
637    elf_height_prev: f32,
638    /// The elf's own vertical speed while off the ground, in meters a
639    /// second, positive upward.
640    jump_speed: f32,
641    elf_input: ElfInput,
642    elf_animator: Animator<Elf, ElfState>,
643    scrubbed_animator: Animator<Elf, ScrubbedState>,
644    butterfly_animator: Animator<Butterfly, FlyingState>,
645    hits: u32,
646    /// True while a hurt patch already held the elf, so leaving and
647    /// returning to the same patch counts as a new hit.
648    in_patch: bool,
649    /// Whether the pointer is held; a click takes it, escape frees it.
650    holding: bool,
651    /// The camera's turn around the elf, and its tilt, both in radians.
652    camera_yaw: f32,
653    camera_pitch: f32,
654    /// The last state change the panel names.
655    last_event: &'static str,
656}
657
658impl Scene {
659    fn init(_ctx: &mut InitContext<'_, Scene>) -> Result<Self, Error> {
660        Ok(Self {
661            elf_pos: ELF_START,
662            elf_prev: ELF_START,
663            elf_yaw: 0.0,
664            elf_height: 0.0,
665            elf_height_prev: 0.0,
666            jump_speed: 0.0,
667            elf_input: ElfInput::default(),
668            elf_animator: Animator::new(),
669            scrubbed_animator: Animator::new(),
670            butterfly_animator: Animator::new(),
671            hits: 0,
672            in_patch: false,
673            holding: false,
674            camera_yaw: 0.0,
675            camera_pitch: 0.0,
676            last_event: "none yet",
677        })
678    }
679
680    /// Turns the camera by how far the pointer moves sideways and upward,
681    /// [`CAMERA_PITCH_RANGE`] holding how far it tilts.
682    fn steer_camera(&mut self, ctx: &mut FrameContext<'_, Scene>) {
683        self.camera_yaw -= ctx.axis(Axis::CameraYaw);
684        self.camera_pitch = (self.camera_pitch + ctx.axis(Axis::CameraPitch))
685            .clamp(CAMERA_PITCH_RANGE.start, CAMERA_PITCH_RANGE.end);
686    }
687
688    /// Turns `elf_yaw` toward the heading `ctx` reads, relative to the
689    /// camera's own turn, and moves `elf_pos` along it; the speed it moves
690    /// at, a fraction of [`ELF_SPEED`], held at [`WALK_CAP`] until
691    /// `Button::Run` is held.
692    fn advance(&mut self, ctx: &mut TickContext<'_, Scene>) -> f32 {
693        let control = ctx.axis2(Move::Walk).clamp_length_max(1.0);
694        let turn = Quat::from_rotation_y(self.camera_yaw);
695        let heading = turn * Vec3::X * control.x + turn * Vec3::NEG_Z * control.y;
696        let dt = ctx.dt().as_secs_f32();
697        if let Some(direction) = heading.try_normalize() {
698            let wanted = direction.x.atan2(direction.z);
699            let turn = (wanted - self.elf_yaw + core::f32::consts::PI).rem_euclid(TAU)
700                - core::f32::consts::PI;
701            self.elf_yaw += turn.clamp(-TURN_RATE * dt, TURN_RATE * dt);
702        }
703        let cap = if ctx.down(Button::Run) { 1.0 } else { WALK_CAP };
704        self.elf_pos += heading * cap * ELF_SPEED * dt;
705        heading.length() * cap
706    }
707
708    /// Integrates [`Self::elf_height`] under [`GRAVITY`] from
709    /// [`Self::jump_speed`], held at the ground; `true` the tick it
710    /// returns there from above it.
711    fn fall(&mut self, dt: f32) -> bool {
712        let off_ground = self.elf_height > 0.0;
713        self.jump_speed -= GRAVITY * dt;
714        self.elf_height = (self.elf_height + self.jump_speed * dt).max(0.0);
715        if self.elf_height == 0.0 {
716            self.jump_speed = 0.0;
717        }
718        off_ground && self.elf_height == 0.0
719    }
720
721    /// The hurt patch `elf_pos` stands inside, if any.
722    fn patch_underfoot(&self) -> Option<Vec3> {
723        HURT_PATCHES
724            .into_iter()
725            .find(|&patch| self.elf_pos.distance(patch) < HURT_RADIUS)
726    }
727
728    /// Reads the controls and moves the elf, filling [`Self::elf_input`]
729    /// for [`ElfState`] to read.
730    fn tick_elf(&mut self, ctx: &mut TickContext<'_, Scene>) {
731        let grounded = matches!(
732            self.elf_animator.state(),
733            ElfState::Idle | ElfState::Locomotion
734        );
735
736        self.elf_input.speed = self.advance(ctx);
737        self.elf_input.attack = ctx.pressed(Button::Attack);
738        self.elf_input.jump = ctx.pressed(Button::Jump);
739        self.elf_input.dance = ctx.pressed(Button::Dance);
740
741        self.elf_input.near_seat = self.elf_pos.distance(SEAT_POSITION) < SEAT_INTERACT_RADIUS;
742        self.elf_input.interact = ctx.pressed(Button::Interact);
743        if self.elf_input.interact && grounded && self.elf_input.near_seat {
744            self.elf_pos = SEAT_SPOT;
745            self.elf_yaw = SEAT_FACING;
746        }
747
748        let underfoot = self.patch_underfoot();
749        let entered_patch = underfoot.is_some() && !self.in_patch;
750        self.in_patch = underfoot.is_some();
751        self.hits += u32::from(entered_patch);
752        self.elf_input.hit = entered_patch && self.hits < FATAL_HITS;
753        self.elf_input.dying = entered_patch && self.hits >= FATAL_HITS;
754        if entered_patch {
755            self.last_event = match self.elf_input.dying {
756                true => "elf died",
757                false => "elf hit",
758            };
759        }
760    }
761
762    /// Starts a new [`Animator`] over the elf's own state, its position and
763    /// hit count reset with it.
764    fn restart_elf(&mut self) {
765        self.elf_animator = Animator::new();
766        self.elf_pos = ELF_START;
767        self.elf_prev = ELF_START;
768        self.elf_yaw = 0.0;
769        self.elf_height = 0.0;
770        self.elf_height_prev = 0.0;
771        self.jump_speed = 0.0;
772        self.elf_input = ElfInput::default();
773        self.hits = 0;
774        self.in_patch = false;
775        self.last_event = "new elf started";
776    }
777
778    fn panel(&self, ctx: &mut FrameContext<'_, Scene>) {
779        let state = match self.elf_animator.state() {
780            ElfState::Idle => "idle",
781            ElfState::Locomotion if self.elf_input.speed > WALK_CAP => "running",
782            ElfState::Locomotion => "walking",
783            ElfState::Attack => "attacking",
784            ElfState::Hit => "hit",
785            ElfState::Death => "dead",
786            ElfState::SitDown => "sitting down",
787            ElfState::Sit => "sitting",
788            ElfState::StandUp => "standing up",
789            ElfState::Jump => "jumping",
790            ElfState::Dance => "dancing",
791        };
792        ctx.ui(|ui| {
793            egui::Frame::new()
794                .fill(egui::Color32::from_black_alpha(PANEL_BACKDROP))
795                .inner_margin(PANEL_PADDING)
796                .corner_radius(f32::from(PANEL_PADDING))
797                .show(ui, |ui| {
798                    ui.heading(panel_text(format!("elf is {state}")));
799                    ui.label(panel_text(format!(
800                        "hits taken {} of the {} red patches hurt for, {}",
801                        self.hits, FATAL_HITS, self.last_event
802                    )));
803                    ui.label(panel_text(match self.elf_animator.transitioning() {
804                        true => "fading between clips",
805                        false => "one clip playing",
806                    }));
807                    ui.add_space(f32::from(PANEL_PADDING));
808                    egui::Grid::new("controls").show(ui, |ui| {
809                        for (key, does) in CONTROLS {
810                            ui.label(panel_text(key));
811                            ui.label(panel_text(does));
812                            ui.end_row();
813                        }
814                    });
815                });
816        });
817    }
818
819    /// A prompt over the seat, each hurt patch, and the scrubbed elf,
820    /// naming what a player finds there; the seat's own prompt names the
821    /// live binding of `Button::Interact` by its own name, not one fixed
822    /// in the code, and is absent while the elf sits on it.
823    fn draw_prompts(&self, ctx: &mut FrameContext<'_, Scene>, camera: Camera) {
824        let sit_key = ctx
825            .bindings(Button::Interact)
826            .into_iter()
827            .next()
828            .map_or_else(|| "interact".to_owned(), |binding| binding.to_string());
829        let sit = ctx.text_layout(
830            &format!("{sit_key} sits"),
831            egui::FontId::proportional(PROMPT_SIZE),
832        );
833        let hurts = ctx.text_layout("hurts", egui::FontId::proportional(PROMPT_SIZE));
834        let walk_closer = ctx.text_layout("walk closer", egui::FontId::proportional(PROMPT_SIZE));
835
836        let mut prompts = vec![(
837            SCRUBBED_ELF_POSITION + Vec3::Y * (ELF_HEIGHT + PROMPT_LIFT),
838            walk_closer,
839        )];
840        if !self.elf_animator.state().seated() {
841            prompts.push((
842                SEAT_POSITION + Vec3::Y * (SEAT_HEAD_HEIGHT + PROMPT_LIFT),
843                sit,
844            ));
845        }
846        prompts.extend(HURT_PATCHES.map(|patch| (patch + Vec3::Y * PROMPT_LIFT, hurts.clone())));
847
848        let window_size = ctx.window_size();
849        let pixels_per_point = ctx.pixels_per_point();
850        ctx.ui(|ui| {
851            let painter = ui.painter();
852            for (point, galley) in prompts {
853                let Some(pixel) = camera.pixel_of(point, window_size) else {
854                    continue;
855                };
856                let at = logical(pixel, pixels_per_point);
857                let ink = galley.mesh_bounds;
858                let pos = egui::pos2(at.x - ink.center().x, at.y - ink.center().y);
859                let backdrop = egui::Rect::from_center_size(
860                    at,
861                    ink.size() + egui::Vec2::splat(PROMPT_PADDING * 2.0),
862                );
863                painter.rect_filled(
864                    backdrop,
865                    PROMPT_PADDING,
866                    egui::Color32::from_black_alpha(PANEL_BACKDROP),
867                );
868                painter.galley(pos, galley, PANEL_TEXT_COLOR);
869            }
870        });
871    }
872}
873
874impl Game for Scene {
875    type Meshes = Shape;
876    type Sounds = NoSounds;
877    type InputActions = Controls;
878    type Skyboxes = Sky;
879    type SurfaceStyles = NoSurfaceStyles;
880    type PostEffects = NoPostEffects;
881
882    fn tick(&mut self, ctx: &mut TickContext<'_, Scene>) {
883        self.elf_prev = self.elf_pos;
884        self.elf_height_prev = self.elf_height;
885
886        if ctx.pressed(Button::Restart) {
887            self.restart_elf();
888        }
889        if ctx.pressed(Button::Hold) {
890            self.holding = true;
891        }
892        if ctx.pressed(Button::Release) {
893            self.holding = false;
894        }
895
896        self.elf_input.landed = self.fall(ctx.dt().as_secs_f32());
897        self.tick_elf(ctx);
898        ctx.animate(Elf, &mut self.elf_animator, &self.elf_input);
899
900        if self.elf_animator.entered(ElfState::Jump) {
901            self.jump_speed = JUMP_LAUNCH_SPEED;
902        }
903        if self.elf_animator.left(ElfState::StandUp) {
904            self.last_event = "elf stood up";
905        }
906        if self.elf_animator.entered(ElfState::Sit) {
907            self.last_event = "elf sat down";
908        }
909        if self.elf_animator.entered(ElfState::Death) {
910            self.last_event = "elf died";
911        }
912
913        let scrubbed_input = ScrubbedInput {
914            settled: settled_at(self.elf_pos.distance(SCRUBBED_ELF_POSITION)),
915        };
916        ctx.animate(Elf, &mut self.scrubbed_animator, &scrubbed_input);
917        ctx.animate(Butterfly, &mut self.butterfly_animator, &());
918    }
919
920    fn frame(&mut self, ctx: &mut FrameContext<'_, Scene>) {
921        self.steer_camera(ctx);
922
923        let alpha = ctx.alpha();
924        let elf_pos = self.elf_prev.lerp(self.elf_pos, alpha);
925        let elf_height = self.elf_height_prev + (self.elf_height - self.elf_height_prev) * alpha;
926        let (butterfly_pos, butterfly_yaw) = butterfly_pose(ctx.elapsed().as_secs_f32());
927
928        let camera = orbit_camera(elf_pos, self.camera_yaw, self.camera_pitch);
929        ctx.set_camera(camera);
930        ctx.set_cursor(if self.holding {
931            Cursor::Held
932        } else {
933            Cursor::Arrow
934        });
935        ctx.set_skybox(Sky::Day);
936        ctx.set_exposure(3.0);
937        ctx.set_bloom(0.2);
938        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
939        ctx.light(
940            Light::point(
941                LAMP_POST_POSITION + Vec3::Y * (LAMP_POST_HEIGHT + LAMP_HEAD_GAP * 0.5),
942                LAMP_LIGHT_COLOR,
943                LAMP_LIGHT_RANGE,
944            )
945            .shadow(),
946        );
947        ctx.light(
948            Light::spot(Spot {
949                position: SPOT_POSITION,
950                direction: SPOT_DIRECTION,
951                color: SPOT_COLOR,
952                range: SPOT_RANGE,
953                angle: SPOT_ANGLE,
954            })
955            .shadow(),
956        );
957        ctx.light(
958            Light::point(butterfly_pos, BUTTERFLY_LIGHT_COLOR, BUTTERFLY_LIGHT_RANGE).shadow(),
959        );
960
961        ctx.draw(
962            Plane
963                .at(Transform::from_scale(Vec3::new(
964                    GROUND_SIZE,
965                    1.0,
966                    GROUND_SIZE,
967                )))
968                .material(Material::lit(GROUND_COLOR)),
969        );
970        for patch in HURT_PATCHES {
971            ctx.draw(
972                Plane
973                    .at(Transform::from_scale_rotation_translation(
974                        Vec3::splat(HURT_RADIUS * 2.0),
975                        Quat::IDENTITY,
976                        patch,
977                    ))
978                    .material(Material::lit(HURT_COLOR)),
979            );
980        }
981        ctx.draw(
982            Cube.at(Transform::from_scale_rotation_translation(
983                Vec3::new(SEAT_FOOTPRINT, SEAT_HEIGHT, SEAT_FOOTPRINT),
984                Quat::IDENTITY,
985                SEAT_POSITION + Vec3::Y * SEAT_HEIGHT * 0.5,
986            ))
987            .material(Material::lit(SEAT_COLOR)),
988        );
989        ctx.draw(
990            Cube.at(Transform::from_scale_rotation_translation(
991                Vec3::new(LAMP_POST_THICKNESS, LAMP_POST_HEIGHT, LAMP_POST_THICKNESS),
992                Quat::IDENTITY,
993                LAMP_POST_POSITION + Vec3::Y * LAMP_POST_HEIGHT * 0.5,
994            ))
995            .material(Material::lit(LAMP_POST_COLOR)),
996        );
997        ctx.draw(
998            Cube.at(Transform::from_scale_rotation_translation(
999                Vec3::splat(LAMP_HEAD_SIZE),
1000                Quat::IDENTITY,
1001                LAMP_POST_POSITION
1002                    + Vec3::Y * (LAMP_POST_HEIGHT + LAMP_HEAD_GAP + LAMP_HEAD_SIZE * 0.5),
1003            ))
1004            .material(Material::color(Color::BLACK).emissive(LAMP_LIGHT_COLOR)),
1005        );
1006        ctx.draw(
1007            Cube.at(Transform::from_scale_rotation_translation(
1008                Vec3::splat(SPOT_FIXTURE_SIZE),
1009                Quat::IDENTITY,
1010                SPOT_POSITION + Vec3::Y * SPOT_FIXTURE_SIZE * 0.5,
1011            ))
1012            .material(Material::lit(SPOT_FIXTURE_COLOR)),
1013        );
1014
1015        ctx.draw(
1016            Elf.at(Transform::from_rotation_translation(
1017                Quat::from_rotation_y(self.elf_yaw),
1018                elf_pos + Vec3::Y * elf_height,
1019            ))
1020            .posed(&self.elf_animator),
1021        );
1022        ctx.draw(
1023            Elf.at(Transform::from_rotation_translation(
1024                Quat::from_rotation_y(core::f32::consts::PI),
1025                SCRUBBED_ELF_POSITION,
1026            ))
1027            .posed(&self.scrubbed_animator),
1028        );
1029        ctx.draw(
1030            Butterfly
1031                .at(Transform::from_rotation_translation(
1032                    Quat::from_rotation_y(butterfly_yaw),
1033                    butterfly_pos,
1034                ))
1035                .posed(&self.butterfly_animator)
1036                .material(Material::lit(Color::WHITE).emissive(BUTTERFLY_EMISSIVE)),
1037        );
1038
1039        self.draw_prompts(ctx, camera);
1040        self.panel(ctx);
1041    }
examples/isometric-board.rs (line 575)
568    fn draw_rocks(&self, ctx: &mut FrameContext<'_, Board>) {
569        for &(x, z, seed, scale) in &ROCKS {
570            let angle = hash_signed(seed, 99) * core::f32::consts::PI;
571            ctx.draw(
572                Rock { seed }
573                    .at(Transform::from_scale_rotation_translation(
574                        Vec3::splat(scale),
575                        Quat::from_rotation_y(angle),
576                        Vec3::new(x, 0.5 * scale, z),
577                    ))
578                    .material(Material::lit(ROCK_COLOR)),
579            );
580        }
581    }
examples/stress-preview.rs (line 413)
403    fn draw_field(&self, ctx: &mut FrameContext<'_, Self>, elapsed: f32) {
404        for entry in &self.field {
405            let yaw = if self.settings.moving && entry.moving {
406                entry.phase + elapsed * MOVING_SPEED
407            } else {
408                entry.phase
409            };
410            ctx.draw(
411                Rock { seed: entry.seed }.at(Transform::from_scale_rotation_translation(
412                    Vec3::ONE,
413                    Quat::from_rotation_y(yaw),
414                    entry.position,
415                )),
416            );
417        }
418    }
Source

pub fn from_rotation_z(angle: f32) -> Quat

Creates a quaternion from the angle (in radians) around the z axis.

Source

pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Quat

Creates a quaternion from the given Euler rotation sequence and the angles (in radians).

Source

pub fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Quat

From the columns of a 3x3 rotation matrix.

Note if the input axes contain scales, shears, or other non-rotation transformations then the output of this function is ill-defined.

§Panics

Will panic if any axis is not normalized when glam_assert is enabled.

Source

pub fn from_mat3(mat: &Mat3) -> Quat

Creates a quaternion from a 3x3 rotation matrix.

Note if the input matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.

§Panics

Will panic if any input matrix column is not normalized when glam_assert is enabled.

Source

pub fn from_mat3a(mat: &Mat3A) -> Quat

Creates a quaternion from a 3x3 SIMD aligned rotation matrix.

Note if the input matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.

§Panics

Will panic if any input matrix column is not normalized when glam_assert is enabled.

Source

pub fn from_mat4(mat: &Mat4) -> Quat

Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.

Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.

§Panics

Will panic if any column of the upper 3x3 rotation matrix is not normalized when glam_assert is enabled.

Source

pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Quat

Gets the minimal rotation for transforming from to to. The rotation is in the plane spanned by the two vectors. Will rotate at most 180 degrees.

The inputs must be unit vectors.

from_rotation_arc(from, to) * from ≈ to.

For near-singular cases (from≈to and from≈-to) the current implementation is only accurate to about 0.001 (for f32).

§Panics

Will panic if from or to are not normalized when glam_assert is enabled.

Examples found in repository?
examples/flock-parallelism.rs (line 676)
674    fn draw_butterflies(&self, ctx: &mut FrameContext<'_, Self>) {
675        for (position, velocity, kind) in self.butterflies.each() {
676            let rotation = Quat::from_rotation_arc(Vec3::Z, Vec3::from(velocity).normalize());
677            ctx.draw(
678                Butterfly
679                    .at(Transform::from_scale_rotation_translation(
680                        Vec3::splat(BUTTERFLY_SCALE),
681                        rotation,
682                        Vec3::from(position),
683                    ))
684                    .posed(&self.flaps[usize::from(kind.flap)])
685                    .material(Material::lit(TINTS[usize::from(kind.tint)])),
686            );
687        }
688    }
Source

pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Quat

Gets the minimal rotation for transforming from to either to or -to. This means that the resulting quaternion will rotate from so that it is colinear with to.

The rotation is in the plane spanned by the two vectors. Will rotate at most 90 degrees.

The inputs must be unit vectors.

to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1.

§Panics

Will panic if from or to are not normalized when glam_assert is enabled.

Source

pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Quat

Gets the minimal rotation for transforming from to to. The resulting rotation is around the z axis. Will rotate at most 180 degrees.

The inputs must be unit vectors.

from_rotation_arc_2d(from, to) * from ≈ to.

For near-singular cases (from≈to and from≈-to) the current implementation is only accurate to about 0.001 (for f32).

§Panics

Will panic if from or to are not normalized when glam_assert is enabled.

Source

pub fn look_to_lh(dir: Vec3, up: Vec3) -> Quat

👎Deprecated since 0.33.1:

use the glam::camera::lh::view::look_to_quat function instead

Creates a quaterion rotation from a facing direction and an up direction.

For a left-handed view coordinate system with +X=right, +Y=up and +Z=forward.

§Panics

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

Source

pub fn look_to_rh(dir: Vec3, up: Vec3) -> Quat

👎Deprecated since 0.33.1:

use the glam::camera::rh::view::look_to_quat function instead

Creates a quaterion rotation from facing direction and an up direction.

For a right-handed view coordinate system with +X=right, +Y=up and +Z=back.

§Panics

Will panic if dir and up are not normalized when glam_assert is enabled.

Source

pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Quat

👎Deprecated since 0.33.1:

use the glam::camera::lh::view::look_at_quat function instead

Creates a quaternion rotation from a camera position, a focal point, and an up direction.

For a left-handed view coordinate system with +X=right, +Y=up and +Z=forward.

§Panics

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

Source

pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Quat

👎Deprecated since 0.33.1:

use the glam::camera::rh::view::look_at_quat function instead

Creates a quaternion rotation using a camera position, an up direction, and a focal point.

For a right-handed view coordinate system with +X=right, +Y=up and +Z=back.

§Panics

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

Source

pub fn to_axis_angle(self) -> (Vec3, f32)

Returns the rotation axis (normalized) and angle (in radians) of self.

Source

pub fn to_scaled_axis(self) -> Vec3

Returns the rotation axis scaled by the rotation in radians.

Source

pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32)

Returns the rotation angles for the given euler rotation sequence.

Source

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

Converts self to [x, y, z, w]

Source

pub fn xyz(self) -> Vec3

Returns the vector part of the quaternion.

Source

pub fn conjugate(self) -> Quat

Returns the quaternion conjugate of self. For a unit quaternion the conjugate is also the inverse.

Source

pub fn inverse(self) -> Quat

Returns the inverse of a normalized quaternion.

Typically quaternion inverse returns the conjugate of a normalized quaternion. Because self is assumed to already be unit length this method does not normalize before returning the conjugate.

§Panics

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

Source

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

Computes the dot product of self and rhs. The dot product is equal to the cosine of the angle between two quaternion rotations.

Source

pub fn length(self) -> f32

Computes the length of self.

Source

pub fn length_squared(self) -> f32

Computes the squared length of self.

This is generally faster than length() as it avoids a square root operation.

Source

pub fn length_recip(self) -> f32

Computes 1.0 / length().

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

Source

pub fn normalize(self) -> Quat

Returns self normalized to length 1.0.

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

Panics

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

Source

pub fn is_finite(self) -> bool

Returns true if, and only if, all elements are finite. If any element is either NaN, positive or negative infinity, this will return false.

Source

pub fn is_nan(self) -> bool

Returns true if any elements are NAN.

Source

pub fn is_normalized(self) -> bool

Returns whether self of length 1.0 or not.

Uses a precision threshold of 1e-6.

Source

pub fn is_near_identity(self) -> bool

Source

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

Returns the angle (in radians) for the minimal rotation between two quaternions in the range [0, +π].

Both quaternions must be normalized.

§Panics

Will panic if self or rhs are not normalized when glam_assert is enabled.

Source

pub fn rotate_towards(self, rhs: Quat, max_angle: f32) -> Quat

Rotates towards rhs up to max_angle (in radians).

When max_angle is 0.0, the result will be equal to self. When max_angle is equal to self.angle_between(rhs), the result will be equal to rhs. If max_angle is negative, rotates towards the exact opposite of rhs. Will not go past the target.

Both quaternions must be normalized.

§Panics

Will panic if self or rhs are not normalized when glam_assert is enabled.

Source

pub fn abs_diff_eq(self, rhs: Quat, max_abs_diff: f32) -> bool

Returns true if the absolute difference of all elements between self and rhs is less than or equal to max_abs_diff.

This can be used to compare if two quaternions contain similar elements. It works best when comparing with a known value. The max_abs_diff that should be used used depends on the values being compared against.

For more see comparing floating point numbers.

Source

pub fn lerp(self, end: Quat, s: f32) -> Quat

Performs a linear interpolation between self and rhs based on the value s.

When s is 0.0, the result will be equal to self. When s is 1.0, the result will be equal to rhs.

§Panics

Will panic if self or end are not normalized when glam_assert is enabled.

Source

pub fn slerp(self, end: Quat, s: f32) -> Quat

Performs a spherical linear interpolation between self and end based on the value s.

When s is 0.0, the result will be equal to self. When s is 1.0, the result will be equal to end.

§Panics

Will panic if self or end are not normalized when glam_assert is enabled.

Source

pub fn slerp_long(self, end: Quat, s: f32) -> Quat

Performs a spherical linear interpolation between self and end based on the value s, preserving the rotation direction.

When s is 0.0, the result will be equal to self. When s is 1.0, the result will be equal to end.

When the dot product of self and end is negative, the standard slerp will flip the end quaternion to take the shortest path, while this method will take the longer arc. This is useful when the intended rotation direction must be preserved.

§Panics

Will panic if self or end are not normalized when glam_assert is enabled.

Source

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

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

§Panics

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

Source

pub fn mul_quat(self, rhs: Quat) -> Quat

Multiplies two quaternions. If they each represent a rotation, the result will represent the combined rotation.

Note that due to floating point rounding the result may not be perfectly normalized.

§Panics

Will panic if self or rhs are not normalized when glam_assert is enabled.

Source

pub fn from_affine3(a: &Affine3) -> Quat

Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.

Note if the input affine matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.

§Panics

Will panic if any input affine matrix column is not normalized when glam_assert is enabled.

Source

pub fn from_affine3a(a: &Affine3A) -> Quat

Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.

Note if the input affine matrix contain scales, shears, or other non-rotation transformations then the resulting quaternion will be ill-defined.

§Panics

Will panic if any input affine matrix column is not normalized when glam_assert is enabled.

Source

pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A

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

Source

pub fn as_dquat(self) -> DQuat

Trait Implementations§

Source§

impl Add for Quat

Source§

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

Adds two quaternions.

The sum is not guaranteed to be normalized.

Note that addition is not the same as combining the rotations represented by the two quaternions! That corresponds to multiplication.

Source§

type Output = Quat

The resulting type after applying the + operator.
Source§

impl Add<&Quat> for Quat

Source§

type Output = Quat

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Quat) -> Quat

Performs the + operation. Read more
Source§

impl Add<&Quat> for &Quat

Source§

type Output = Quat

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Quat) -> Quat

Performs the + operation. Read more
Source§

impl Add<Quat> for &Quat

Source§

type Output = Quat

The resulting type after applying the + operator.
Source§

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

Performs the + operation. Read more
Source§

impl AddAssign for Quat

Source§

fn add_assign(&mut self, rhs: Quat)

Performs the += operation. Read more
Source§

impl AddAssign<&Quat> for Quat

Source§

fn add_assign(&mut self, rhs: &Quat)

Performs the += operation. Read more
Source§

impl AsRef<[f32; 4]> for Quat

Source§

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

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

impl Clone for Quat

Source§

fn clone(&self) -> Quat

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Copy for Quat

Source§

impl Debug for Quat

Source§

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

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

impl Default for Quat

Source§

fn default() -> Quat

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

impl Deref for Quat

Source§

type Target = Vec4<f32>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &<Quat as Deref>::Target

Dereferences the value.
Source§

impl DerefMut for Quat

Source§

fn deref_mut(&mut self) -> &mut <Quat as Deref>::Target

Mutably dereferences the value.
Source§

impl Display for Quat

Source§

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

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

impl Div<&f32> for Quat

Source§

type Output = Quat

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &f32) -> Quat

Performs the / operation. Read more
Source§

impl Div<&f32> for &Quat

Source§

type Output = Quat

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &f32) -> Quat

Performs the / operation. Read more
Source§

impl Div<f32> for Quat

Source§

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

Divides a quaternion by a scalar value. The quotient is not guaranteed to be normalized.

Source§

type Output = Quat

The resulting type after applying the / operator.
Source§

impl Div<f32> for &Quat

Source§

type Output = Quat

The resulting type after applying the / operator.
Source§

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

Performs the / operation. Read more
Source§

impl DivAssign<&f32> for Quat

Source§

fn div_assign(&mut self, rhs: &f32)

Performs the /= operation. Read more
Source§

impl DivAssign<f32> for Quat

Source§

fn div_assign(&mut self, rhs: f32)

Performs the /= operation. Read more
Source§

impl From<Quat> for Vec4

Source§

fn from(q: Quat) -> Vec4

Converts to this type from the input type.
Source§

impl Mul for Quat

Source§

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

Multiplies two quaternions. If they each represent a rotation, the result will represent the combined rotation.

Note that due to floating point rounding the result may not be perfectly normalized.

§Panics

Will panic if self or rhs are not normalized when glam_assert is enabled.

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

impl Mul<&Quat> for Quat

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Quat) -> Quat

Performs the * operation. Read more
Source§

impl Mul<&Quat> for &Quat

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Quat) -> Quat

Performs the * operation. Read more
Source§

impl Mul<&Vec3> for Quat

Source§

type Output = Vec3

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl Mul<&Vec3> for &Quat

Source§

type Output = Vec3

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl Mul<&Vec3A> for Quat

Source§

type Output = Vec3A

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec3A) -> Vec3A

Performs the * operation. Read more
Source§

impl Mul<&Vec3A> for &Quat

Source§

type Output = Vec3A

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec3A) -> Vec3A

Performs the * operation. Read more
Source§

impl Mul<&f32> for Quat

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &f32) -> Quat

Performs the * operation. Read more
Source§

impl Mul<&f32> for &Quat

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &f32) -> Quat

Performs the * operation. Read more
Source§

impl Mul<Quat> for &Quat

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl Mul<Vec3> for Quat

Source§

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

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

§Panics

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

Source§

type Output = Vec3

The resulting type after applying the * operator.
Source§

impl Mul<Vec3> for &Quat

Source§

type Output = Vec3

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl Mul<Vec3A> for Quat

Source§

type Output = Vec3A

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl Mul<Vec3A> for &Quat

Source§

type Output = Vec3A

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl Mul<f32> for Quat

Source§

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

Multiplies a quaternion by a scalar value.

The product is not guaranteed to be normalized.

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

impl Mul<f32> for &Quat

Source§

type Output = Quat

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl MulAssign for Quat

Source§

fn mul_assign(&mut self, rhs: Quat)

Performs the *= operation. Read more
Source§

impl MulAssign<&Quat> for Quat

Source§

fn mul_assign(&mut self, rhs: &Quat)

Performs the *= operation. Read more
Source§

impl MulAssign<&f32> for Quat

Source§

fn mul_assign(&mut self, rhs: &f32)

Performs the *= operation. Read more
Source§

impl MulAssign<f32> for Quat

Source§

fn mul_assign(&mut self, rhs: f32)

Performs the *= operation. Read more
Source§

impl Neg for Quat

Source§

type Output = Quat

The resulting type after applying the - operator.
Source§

fn neg(self) -> Quat

Performs the unary - operation. Read more
Source§

impl Neg for &Quat

Source§

type Output = Quat

The resulting type after applying the - operator.
Source§

fn neg(self) -> Quat

Performs the unary - operation. Read more
Source§

impl PartialEq for Quat

Source§

fn eq(&self, rhs: &Quat) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

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

Inequality operator !=. Read more
Source§

impl Pod for Quat

Source§

impl Product for Quat

Source§

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

Takes an iterator and generates Self from the elements by multiplying the items.
Source§

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

Source§

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

Takes an iterator and generates Self from the elements by multiplying the items.
Source§

impl Sub for Quat

Source§

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

Subtracts the rhs quaternion from self.

The difference is not guaranteed to be normalized.

Source§

type Output = Quat

The resulting type after applying the - operator.
Source§

impl Sub<&Quat> for Quat

Source§

type Output = Quat

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Quat) -> Quat

Performs the - operation. Read more
Source§

impl Sub<&Quat> for &Quat

Source§

type Output = Quat

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Quat) -> Quat

Performs the - operation. Read more
Source§

impl Sub<Quat> for &Quat

Source§

type Output = Quat

The resulting type after applying the - operator.
Source§

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

Performs the - operation. Read more
Source§

impl SubAssign for Quat

Source§

fn sub_assign(&mut self, rhs: Quat)

Performs the -= operation. Read more
Source§

impl SubAssign<&Quat> for Quat

Source§

fn sub_assign(&mut self, rhs: &Quat)

Performs the -= operation. Read more
Source§

impl Sum for Quat

Source§

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

Takes an iterator and generates Self from the elements by “summing up” the items.
Source§

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

Source§

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

Takes an iterator and generates Self from the elements by “summing up” the items.
Source§

impl Zeroable for Quat

Source§

fn zeroed() -> Self

Auto Trait Implementations§

§

impl Freeze for Quat

§

impl RefUnwindSafe for Quat

§

impl Send for Quat

§

impl Sync for Quat

§

impl Unpin for Quat

§

impl UnsafeUnpin for Quat

§

impl UnwindSafe for Quat

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

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

Source§

type Bits = T

Self must have the same layout as the specified Bits except for the possible invalid bit patterns being checked during is_valid_bit_pattern.
Source§

fn is_valid_bit_pattern(_bits: &T) -> bool

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

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

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

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

Source§

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

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

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

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

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

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

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

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

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

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

Source§

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

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

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

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

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

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

fn in_current_span(self) -> Instrumented<Self>

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

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

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<T> IntoEither for T

Source§

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

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

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

Initializes a with the given initializer. Read more
Source§

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

Dereferences the given pointer. Read more
Source§

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

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

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

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> SerializableAny for T
where T: 'static + Any + Clone + for<'a> Send + Sync,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

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

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

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

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

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

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

Source§

fn to_sample_(self) -> U

Source§

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

Source§

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

Source§

fn to_string(&self) -> String

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

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

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

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

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

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

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

Source§

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

Source§

impl<T> WasmNotSendSync for T

Source§

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

Source§

impl<T> WithSubscriber for T

Source§

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

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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