solstice-2d 0.2.21

Easy, cross-platform 2D graphics.
Documentation
use crate::d3::Vertex3D;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Box {
    pub width: f32,
    pub height: f32,
    pub depth: f32,
    pub width_segments: u32,
    pub height_segments: u32,
    pub depth_segments: u32,
}

impl Box {
    pub fn new(
        width: f32,
        height: f32,
        depth: f32,
        width_segments: u32,
        height_segments: u32,
        depth_segments: u32,
    ) -> Self {
        Self {
            width,
            height,
            depth,
            width_segments,
            height_segments,
            depth_segments,
        }
    }

    fn vertices(&self) -> Vec<Vertex3D> {
        let mut vertices = Vec::new();

        build_plane(
            &mut vertices,
            2,
            1,
            0,
            -1.,
            -1.,
            self.depth,
            self.height,
            self.width,
            self.depth_segments,
            self.height_segments,
        );
        build_plane(
            &mut vertices,
            2,
            1,
            0,
            1.,
            -1.,
            self.depth,
            self.height,
            -self.width,
            self.depth_segments,
            self.height_segments,
        );
        build_plane(
            &mut vertices,
            0,
            2,
            1,
            1.,
            1.,
            self.width,
            self.depth,
            self.height,
            self.width_segments,
            self.depth_segments,
        );
        build_plane(
            &mut vertices,
            0,
            2,
            1,
            1.,
            -1.,
            self.width,
            self.depth,
            -self.height,
            self.width_segments,
            self.depth_segments,
        );
        build_plane(
            &mut vertices,
            0,
            1,
            2,
            1.,
            -1.,
            self.width,
            self.height,
            self.depth,
            self.width_segments,
            self.height_segments,
        );
        build_plane(
            &mut vertices,
            0,
            1,
            2,
            -1.,
            -1.,
            self.width,
            self.height,
            -self.depth,
            self.width_segments,
            self.height_segments,
        );

        vertices
    }

    fn indices(&self) -> Vec<u32> {
        let faces = [
            (self.depth_segments, self.height_segments),
            (self.depth_segments, self.height_segments),
            (self.width_segments, self.depth_segments),
            (self.width_segments, self.depth_segments),
            (self.width_segments, self.height_segments),
            (self.width_segments, self.height_segments),
        ];

        let mut index_start = 0;
        let mut indices = Vec::new();
        for (grid_x, grid_y) in faces.iter().copied() {
            let grid_x1 = grid_x + 1;
            for iy in 0..grid_y {
                for ix in 0..grid_x {
                    let a = ix + grid_x1 * iy;
                    let b = ix + grid_x1 * (iy + 1);
                    let c = (ix + 1) + grid_x1 * (iy + 1);
                    let d = (ix + 1) + grid_x1 * iy;

                    indices.push(index_start + a);
                    indices.push(index_start + b);
                    indices.push(index_start + d);

                    indices.push(index_start + b);
                    indices.push(index_start + c);
                    indices.push(index_start + d);
                }
            }
            index_start += grid_x * grid_y * 4;
        }

        indices
    }
}

impl Default for Box {
    fn default() -> Self {
        Self {
            width: 1.,
            height: 1.,
            depth: 1.,
            width_segments: 1,
            height_segments: 1,
            depth_segments: 1,
        }
    }
}

impl From<&Box> for crate::Geometry<'_, Vertex3D> {
    fn from(b: &Box) -> Self {
        Self::new(b.vertices(), Some(b.indices()))
    }
}

impl From<Box> for crate::Geometry<'_, Vertex3D> {
    fn from(b: Box) -> Self {
        Self::new(b.vertices(), Some(b.indices()))
    }
}

fn build_plane(
    vertices: &mut Vec<Vertex3D>,
    u: usize,
    v: usize,
    w: usize,
    u_dir: f32,
    v_dir: f32,
    width: f32,
    height: f32,
    depth: f32,
    grid_x: u32,
    grid_y: u32,
) {
    let segment_width = width / grid_x as f32;
    let segment_height = height / grid_y as f32;

    let width_half = width / 2.;
    let height_half = height / 2.;
    let depth_half = depth / 2.;

    let grid_x1 = grid_x + 1;
    let grid_y1 = grid_y + 1;

    for iy in 0..grid_y1 {
        let iy = iy as f32;
        let y = iy * segment_height - height_half;
        for ix in 0..grid_x1 {
            let ix = ix as f32;
            let x = ix * segment_width - width_half;

            let mut position = [0f32; 3];
            position[u] = x * u_dir;
            position[v] = y * v_dir;
            position[w] = depth_half;

            let mut normal = [0f32; 3];
            normal[u] = 0.;
            normal[v] = 0.;
            normal[w] = if depth > 0. { 1. } else { -1. };

            vertices.push(Vertex3D {
                position,
                normal,
                uv: [ix / grid_x as f32, iy / grid_y as f32],
                color: [1., 1., 1., 1.],
            })
        }
    }
}