jkvargas / russimp

Assimp bindings for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The Right way to use russimp

Snowiiii opened this issue · comments

Hello, as I mentioned in #51, I have some problems. I've already spent multiple hours trying to find the problem, but I still don't know why. So this is the result I get:

Loading Model Node: $MergedNode_0
Loading Model Node: sponza_378_sponza_378_Material__25
Loading Mesh: sponza_378_sponza_378_Material__25
Loading Model Node: sponza_378_sponza_378_Material__298
Loading Mesh: sponza_378_sponza_378_Material__298
Loading Model Node: sponza_257_sponza_257_Material__47
Loading Mesh: sponza_257_sponza_257_Material__47
Loading Model Node: sponza_369_sponza_369_Material__57
Loading Mesh: sponza_369_sponza_369_Material__57
Loading Model Node: sponza_39_sponza_39_arch
Loading Mesh: sponza_39_sponza_39_arch
Loading Model Node: sponza_382_sponza_382_bricks
Loading Mesh: sponza_382_sponza_382_bricks
Loading Model Node: sponza_38_sponza_38_ceiling
Loading Mesh: sponza_38_sponza_38_ceiling
Loading Model Node: sponza_339_sponza_339_chain
Loading Mesh: sponza_339_sponza_339_chain
Loading Model Node: sponza_10_sponza_10_column_a
Loading Mesh: sponza_10_sponza_10_column_a
Loading Model Node: sponza_141_sponza_141_column_b
Loading Mesh: sponza_141_sponza_141_column_b
Loading Model Node: sponza_83_sponza_83_column_c
Loading Mesh: sponza_83_sponza_83_column_c
Loading Model Node: sponza_72_sponza_72_details
Loading Mesh: sponza_72_sponza_72_details
Loading Model Node: sponza_288_sponza_288_fabric_a
Loading Mesh: sponza_288_sponza_288_fabric_a
Loading Model Node: sponza_325_sponza_325_fabric_c
Loading Mesh: sponza_325_sponza_325_fabric_c
Loading Model Node: sponza_289_sponza_289_fabric_d
Loading Mesh: sponza_289_sponza_289_fabric_d
Loading Model Node: sponza_285_sponza_285_fabric_e
Loading Mesh: sponza_285_sponza_285_fabric_e
Loading Model Node: sponza_327_sponza_327_fabric_f
Loading Mesh: sponza_327_sponza_327_fabric_f
Loading Model Node: sponza_326_sponza_326_fabric_g
Loading Mesh: sponza_326_sponza_326_fabric_g
Loading Model Node: sponza_271_sponza_271_flagpole
Loading Mesh: sponza_271_sponza_271_flagpole
Loading Model Node: sponza_18_sponza_18_floor
Loading Mesh: sponza_18_sponza_18_floor
Loading Model Node: sponza_275_sponza_275_leaf
Loading Mesh: sponza_275_sponza_275_leaf
Loading Model Node: sponza_381_sponza_381_roof
Loading Mesh: sponza_381_sponza_381_roof
Loading Model Node: sponza_373_sponza_373_vase
Loading Mesh: sponza_373_sponza_373_vase
Loading Model Node: sponza_344_sponza_344_vase_hanging
Loading Mesh: sponza_344_sponza_344_vase_hanging
Loading Model Node: sponza_369_sponza_369_vase_round
Loading Mesh: sponza_369_sponza_369_vase_round
Creating New Mesh Buffer with 1728 Vertices & 9126 Indices
Creating New Mesh Buffer with 2241 Vertices & 12258 Indices
Creating New Mesh Buffer with 16 Vertices & 54 Indices
Creating New Mesh Buffer with 3932 Vertices & 10416 Indices
Creating New Mesh Buffer with 6583 Vertices & 30504 Indices
Creating New Mesh Buffer with 975 Vertices & 2388 Indices
Creating New Mesh Buffer with 4920 Vertices & 17628 Indices
Creating New Mesh Buffer with 64 Vertices & 96 Indices
Creating New Mesh Buffer with 2222 Vertices & 8448 Indices
Creating New Mesh Buffer with 15936 Vertices & 69624 Indices
Creating New Mesh Buffer with 6428 Vertices & 21264 Indices
Creating New Mesh Buffer with 906 Vertices & 2640 Indices
Creating New Mesh Buffer with 5636 Vertices & 33024 Indices
Creating New Mesh Buffer with 9480 Vertices & 56832 Indices
Creating New Mesh Buffer with 8454 Vertices & 49536 Indices
Creating New Mesh Buffer with 8454 Vertices & 49536 Indices
Creating New Mesh Buffer with 7174 Vertices & 43008 Indices
Creating New Mesh Buffer with 7174 Vertices & 43008 Indices
Creating New Mesh Buffer with 10146 Vertices & 49488 Indices
Creating New Mesh Buffer with 23 Vertices & 63 Indices
Creating New Mesh Buffer with 23085 Vertices & 94308 Indices
Creating New Mesh Buffer with 10730 Vertices & 43452 Indices
Creating New Mesh Buffer with 5308 Vertices & 27552 Indices
Creating New Mesh Buffer with 10412 Vertices & 59484 Indices
Creating New Mesh Buffer with 9584 Vertices & 53064 Indices
[2023-07-03T06:20:18Z ERROR wgpu::backend::direct] Handling wgpu errors as fatal by default
Crash: panicked at 'wgpu error: Validation Error

Caused by:
    In a RenderPass
      note: encoder = `Runtime Render Encoder`
    In a draw command, indexed:true indirect:false
      note: render pipeline = `3D Renderer Pipeline`
    Index 69624 extends beyond limit 53064. Did you bind the correct index buffer?

It seems like Wgpu doesn't like the number of indices. I tried splitting the indices in half (indices.len() / 2), and while it loaded without errors, the final scene looked really strange. So that's not the right approach. Can you please help and tell me what I'm doing wrong?

use std::rc::Rc;

use crate::Asset;
use glam::{Quat, Vec3};
use russimp::mesh::Mesh;
use russimp::node::Node;
use vent_common::render::Vertex3D;
use wgpu::util::DeviceExt;
use wgpu::Device;

pub struct Model3D {
    pub position: glam::Vec3,
    pub rotation: glam::Quat,
    pub scale: glam::Vec3,
    meshes: Vec<Mesh3D>,
}

impl Model3D {
    #[inline(always)]
    pub fn new(device: &Device, path: &str) -> Self {
        let scene = RawMesh::load_full(path);
        let meshes = scene
            .into_iter()
            .map(|mesh| Mesh3D::new(device, mesh.vertices, mesh.indices))
            .collect();

        Self {
            position: Vec3::ZERO,
            rotation: Quat::IDENTITY,
            scale: Vec3::ONE,
            meshes,
        }
    }

    pub fn bind<'rp>(&'rp self, rpass: &mut wgpu::RenderPass<'rp>) {
        for mesh in &self.meshes {
            mesh.bind(rpass)
        }
    }

    pub fn draw<'rp>(&'rp self, rpass: &mut wgpu::RenderPass<'rp>) {
        for mesh in &self.meshes {
            mesh.draw(rpass)
        }
    }
}

impl Asset for Model3D {
    fn get_file_extensions() -> &'static str {
        ""
    }
}

pub struct Mesh3D {
    vertex_buf: wgpu::Buffer,
    index_buf: wgpu::Buffer,

    index_count: u32,
}

impl Mesh3D {
    pub fn new(device: &Device, vertices: Vec<Vertex3D>, indices: Vec<u32>) -> Self {
        println!(
            "Creating New Mesh Buffer with {} Vertices & {} Indices",
            vertices.len(),
            indices.len()
        );
        let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
            label: Some("Vertex Buffer"),
            contents: bytemuck::cast_slice(&vertices),
            usage: wgpu::BufferUsages::VERTEX,
        });

        let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
            label: Some("Index Buffer"),
            contents: bytemuck::cast_slice(&indices),
            usage: wgpu::BufferUsages::INDEX,
        });

        let index_count = indices.len() as u32;

        Self {
            vertex_buf,
            index_buf,
            index_count,
        }
    }

    pub fn bind<'rp>(&'rp self, rpass: &mut wgpu::RenderPass<'rp>) {
        rpass.set_vertex_buffer(0, self.vertex_buf.slice(..));
        rpass.set_index_buffer(self.index_buf.slice(..), wgpu::IndexFormat::Uint32);
    }

    pub fn draw<'rp>(&'rp self, rpass: &mut wgpu::RenderPass<'rp>) {
        rpass.draw_indexed(0..self.index_count, 0, 0..1);
    }
}

use russimp::scene::{PostProcess, Scene};

struct RawMesh {
    pub vertices: Vec<Vertex3D>,
    pub indices: Vec<u32>,
}

impl RawMesh {
    #[inline]
    #[must_use]
    pub fn load_full(path: &str) -> Vec<Self> {
        let scene = russimp::scene::Scene::from_file(
            path,
            vec![
                PostProcess::GenerateSmoothNormals,
                PostProcess::JoinIdenticalVertices,
                PostProcess::Triangulate,
                PostProcess::FixInfacingNormals,
                PostProcess::FlipUVs,
                PostProcess::ValidateDataStructure,
                PostProcess::PreTransformVertices,
                PostProcess::MakeLeftHanded,
                PostProcess::OptimizeMeshes,
                PostProcess::OptimizeGraph,
                PostProcess::ImproveCacheLocality,
            ],
        )
        .expect("Failed to Load Scene");

        let mut meshes = Vec::new();
        Self::load_node(
            &scene.root.clone().expect("Failed to get Scene Root Node"),
            &scene,
            &mut meshes,
        );
        meshes
    }

    fn load_node(node: &Rc<Node>, scene: &Scene, meshes: &mut Vec<RawMesh>) {
        println!("Loading Model Node: {}", node.name);
        for mesh in &node.meshes {
            meshes.push(Self::load_mesh(&scene.meshes[*mesh as usize]))
        }

        for node in node.children.borrow().iter() {
            Self::load_node(node, scene, meshes);
        }
    }

    fn load_mesh(mesh: &Mesh) -> Self {
        println!("Loading Mesh: {}", mesh.name);
        let mut vertices = Vec::with_capacity(mesh.vertices.len());

        for i in 0..mesh.vertices.len() {
            let mut vertex = Vertex3D::empty();

            let mesh_vertex = &mesh.vertices[i];
            vertex.pos = [mesh_vertex.x, mesh_vertex.y, mesh_vertex.z];

            if mesh.texture_coords[0].is_some() {
                let coord = &mesh.texture_coords[0]
                    .as_ref()
                    .expect("Failed to get texture coords")[i];
                vertex.tex_coord = [coord.x, coord.y]
            }
            vertices.push(vertex);
        }

        let indices = mesh
            .faces
            .iter()
            .flat_map(|face| face.0.iter().copied())
            .collect();

        Self { vertices, indices }
    }
}
``

is the model something you can share?

Yes, I tried loading two Sponza models:

The simple .obj model: Sponza
The more advanced .gltf 2.0 model: Sponza

Unfortunately, both models resulted in an error.

Hey i figuired it out, But Thanks