Raw File
/*
ENSnano, a 3d graphical application for DNA nanostructures.
    Copyright (C) 2021  Nicolas Levy <nicolaspierrelevy@gmail.com> and Nicolas Schabanel <nicolas.schabanel@ens-lyon.fr>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
use crate::consts::*;
use iced_wgpu::wgpu;
use std::ops::Range;

pub trait Vertex {
    fn desc<'a>() -> wgpu::VertexBufferLayout<'a>;
}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MeshVertex {
    position: [f32; 3],
    normal: [f32; 3],
}

unsafe impl bytemuck::Pod for MeshVertex {}
unsafe impl bytemuck::Zeroable for MeshVertex {}

impl Vertex for MeshVertex {
    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
        use std::mem;
        wgpu::VertexBufferLayout {
            array_stride: mem::size_of::<MeshVertex>() as wgpu::BufferAddress,
            step_mode: wgpu::InputStepMode::Vertex,
            attributes: &[
                // Position
                wgpu::VertexAttribute {
                    offset: 0,
                    shader_location: VERTEX_POSITION_ADRESS,
                    format: wgpu::VertexFormat::Float3,
                },
                // Normal
                wgpu::VertexAttribute {
                    offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
                    shader_location: VERTEX_NORMAL_ADRESS,
                    format: wgpu::VertexFormat::Float3,
                },
            ],
        }
    }
}

pub struct Mesh {
    pub vertex_buffer: wgpu::Buffer,
    pub index_buffer: wgpu::Buffer,
    pub num_elements: u32,
}

pub trait DrawModel<'a, 'b>
where
    'b: 'a,
{
    fn draw_mesh(
        &mut self,
        mesh: &'b Mesh,
        viewer: &'b wgpu::BindGroup,
        instance_bg: &'b wgpu::BindGroup,
        light: &'b wgpu::BindGroup,
        model_matrices: &'b wgpu::BindGroup,
    );
    fn draw_mesh_instanced(
        &mut self,
        mesh: &'b Mesh,
        instances: Range<u32>,
        viewer: &'b wgpu::BindGroup,
        instances_bg: &'b wgpu::BindGroup,
        light: &'b wgpu::BindGroup,
        model_matrices: &'b wgpu::BindGroup,
    );
}

impl<'a, 'b> DrawModel<'a, 'b> for wgpu::RenderPass<'a>
where
    'b: 'a,
{
    fn draw_mesh(
        &mut self,
        mesh: &'b Mesh,
        viewer: &'b wgpu::BindGroup,
        instances_bg: &'b wgpu::BindGroup,
        light: &'b wgpu::BindGroup,
        model_matrices: &'b wgpu::BindGroup,
    ) {
        self.draw_mesh_instanced(mesh, 0..1, viewer, instances_bg, light, model_matrices);
    }

    fn draw_mesh_instanced(
        &mut self,
        mesh: &'b Mesh,
        instances: Range<u32>,
        viewer: &'b wgpu::BindGroup,
        instances_bg: &'b wgpu::BindGroup,
        light: &'b wgpu::BindGroup,
        model_matrices: &'b wgpu::BindGroup,
    ) {
        self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
        self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
        self.set_bind_group(VIEWER_BINDING_ID, &viewer, &[]);
        self.set_bind_group(INSTANCES_BINDING_ID, &instances_bg, &[]);
        self.set_bind_group(LIGHT_BINDING_ID, &light, &[]);
        self.set_bind_group(MODEL_BINDING_ID, &model_matrices, &[]);
        //self.draw_indexed(0..mesh.num_elements, 0, instances);
        self.draw_indexed(0..mesh.num_elements, 0, instances);
    }
}
back to top