twgpu 0.4.1

Render Teeworlds and DDNet maps
Documentation
use crate::buffer::{GpuArrayBuffer, GpuDeviceExt};
use twmap::{Quad, QuadsLayer};
use vek::az::UnwrappedAs;
use vek::Vec2;
use wgpu::{BufferUsages, Device};

use super::super::{GpuEnvelopesData, QuadCorner};

const LABEL: Option<&str> = Some("Quads Data");

pub struct GpuQuadsData {
    pub vertex_buffer: GpuArrayBuffer<QuadCorner>,
    pub index_buffer: GpuArrayBuffer<u32>,
}

impl QuadCorner {
    fn split_quad(quad: &Quad, envelopes: &GpuEnvelopesData) -> [Self; 4] {
        [0, 1, 2, 3].map(|i| {
            let position: Vec2<f32> = quad.corners[i].az();
            let center: Vec2<f32> = quad.position.az();
            Self {
                center,
                offset: position - center,
                tex_coords: quad.texture_coords[i].az(),
                color: quad.colors[i].az::<f32>() / u8::MAX as f32,
                color_env: envelopes.quad_color_env_index(quad),
                position_env: envelopes.quad_position_env_index(quad),
            }
        })
    }
}

impl GpuQuadsData {
    pub fn upload(layer: &QuadsLayer, envelopes: &GpuEnvelopesData, device: &Device) -> Self {
        let mut vertices = Vec::new();
        let mut indices: Vec<u32> = Vec::new();
        for (n, quad) in layer.quads.iter().enumerate() {
            vertices.extend(QuadCorner::split_quad(quad, envelopes));
            let offset = n.unwrapped_as::<u32>().checked_mul(4).unwrap();
            indices.extend([0, 1, 3, 0, 2, 3].map(|i| i + offset));
        }
        let vertex_buffer = device.array_buffer(&vertices, LABEL, BufferUsages::VERTEX);
        let index_buffer = device.array_buffer(&indices, LABEL, BufferUsages::INDEX);
        Self {
            vertex_buffer,
            index_buffer,
        }
    }
}