Skip to main content

wisp_storybook/stories/
s_mesh_perspective.rs

1//! Story: Mesh with Y-axis perspective rotation, animated (M0.19).
2
3use glam::Vec2;
4use wisp::application::Application;
5use wisp::{Mesh, Stage, Texture};
6
7use crate::story::Story;
8
9pub fn story() -> Story {
10    Story {
11        id: "mesh-perspective",
12        category: "Scene Graph",
13        title: "Perspective rotation",
14        milestone: "M0.19",
15        writeup: include_str!("writeups/mesh_perspective.md"),
16        build,
17        tick: Some(tick),
18    }
19}
20
21fn build(app: &Application, stage: &mut Stage) {
22    let texture = checker_texture(app);
23    let mut mesh = Mesh::from_texture(texture).with_perspective(0.5);
24    mesh.container.transform.scale = Vec2::splat(0.5);
25    let _ = stage.add_child(stage.root(), mesh);
26}
27
28fn tick(stage: &mut Stage, t: f32) {
29    let child_ids: Vec<_> = stage
30        .get(stage.root())
31        .map(|n| n.container().children().collect())
32        .unwrap_or_default();
33    if let Some(id) = child_ids.first()
34        && let Some(node) = stage.get_mut(*id)
35        && let wisp::Node::Mesh(mesh) = node
36    {
37        mesh.rotation_y = t * 0.6;
38    }
39}
40
41fn checker_texture(app: &Application) -> Texture {
42    let size = 64u32;
43    let mut bytes = Vec::with_capacity((size * size * 4) as usize);
44    for y in 0..size {
45        for x in 0..size {
46            let cell_x = (x / 8) % 2;
47            let cell_y = (y / 8) % 2;
48            let dark = (cell_x ^ cell_y) == 1;
49            if dark {
50                bytes.extend_from_slice(&[80, 200, 255, 255]);
51            } else {
52                bytes.extend_from_slice(&[255, 220, 100, 255]);
53            }
54        }
55    }
56    Texture::from_rgba(app, size, size, &bytes)
57}