Skip to main content

myth_resources/primitives/
plane.rs

1use crate::geometry::{Attribute, Geometry};
2use wgpu::VertexFormat;
3
4pub struct PlaneOptions {
5    pub width: f32,
6    pub height: f32,
7    pub width_segments: u32,
8    pub height_segments: u32,
9}
10
11impl Default for PlaneOptions {
12    fn default() -> Self {
13        Self {
14            width: 1.0,
15            height: 1.0,
16            width_segments: 1,
17            height_segments: 1,
18        }
19    }
20}
21
22#[must_use]
23pub fn create_plane(options: &PlaneOptions) -> Geometry {
24    let width_half = options.width / 2.0;
25    let height_half = options.height / 2.0;
26
27    let grid_x = options.width_segments;
28    let grid_y = options.height_segments;
29
30    let grid_cols = grid_x + 1;
31    let grid_rows = grid_y + 1;
32
33    let segment_width = options.width / grid_x as f32;
34    let segment_height = options.height / grid_y as f32;
35
36    let mut positions = Vec::new();
37    let mut normals: Vec<[f32; 3]> = Vec::new();
38    let mut uvs = Vec::new();
39    let mut indices = Vec::new();
40
41    for iy in 0..grid_rows {
42        let y = iy as f32 * segment_height - height_half;
43        for ix in 0..grid_cols {
44            let x = ix as f32 * segment_width - width_half;
45
46            positions.push([x, -y, 0.0]); // Note: -y to match UV direction
47            normals.push([0.0, 0.0, 1.0]);
48            uvs.push([ix as f32 / grid_x as f32, 1.0 - (iy as f32 / grid_y as f32)]);
49        }
50    }
51
52    // Indices
53    for iy in 0..grid_y {
54        for ix in 0..grid_x {
55            let a = ix + grid_cols * iy;
56            let b = ix + grid_cols * (iy + 1);
57            let c = (ix + 1) + grid_cols * (iy + 1);
58            let d = (ix + 1) + grid_cols * iy;
59
60            indices.push(a as u16);
61            indices.push(b as u16);
62            indices.push(d as u16);
63
64            indices.push(b as u16);
65            indices.push(c as u16);
66            indices.push(d as u16);
67        }
68    }
69
70    let mut geo = Geometry::new();
71    geo.set_attribute(
72        "position",
73        Attribute::new_planar(&positions, VertexFormat::Float32x3),
74    );
75    geo.set_attribute(
76        "normal",
77        Attribute::new_planar(&normals, VertexFormat::Float32x3),
78    );
79    geo.set_attribute("uv", Attribute::new_planar(&uvs, VertexFormat::Float32x2));
80    geo.set_indices(&indices);
81    geo.compute_bounding_volume();
82
83    geo
84}