New to Amethyst, trying to display a generated mesh, would like some help

(Martin) #1

I am trying to display a mesh that I have generated myself. I have half written the code for the mesh, but I’m not sure what I need to do to make it build and run.

First, I have written two functions, which create a mesh and a PNG that will be UV mapped onto the mesh.

pub fn make_mesh() -> ( // returns (mesh_points, mesh_triangles, uvs)
    Vec<na::Point3<f32>>,
    Vec<na::Point3<u16>>,
    Vec<na::Point2<f32>>,
) 

and

pub fn make_image() -> image::DynamicImage

Now I call these functions, and then try to use them in some simple code, which is basically the standard Amethyst example code.

        let (mesh_points, mesh_triangles, uvs) = make_data::make_mesh();
        let image = make_data::make_image();
        let (mesh, albedo) = {
            let mesh = world.exec(|loader: AssetLoaderSystemData<'_, Mesh>| {
                loader.load_from_data(
                    MeshBuilder::new()
                        .with_vertices(mesh_points)
                        .build()
                        .unwrap()
                        .into(),
                    (),
                )
            });
            let image_data = load_from_image(
                image,
                ImageTextureConfig {
                    format: Some(ImageFormat::PNG),
                    sampler_info: SamplerInfo::new(Filter::Linear, WrapMode::Border),
                    ..ImageTextureConfig::default()
                },
            )
            .unwrap()
            .build()
            .unwrap();
            let albedo = world.exec(|loader: AssetLoaderSystemData<'_, Texture>| {
                loader.load_from_data(image_data, ())
            });

            (mesh, albedo)
        };

This is not building at all. I just have no idea at this stage which types and methods I should be using.

The Amethyst documentation is a bit light on at this point, so I would welcome any advice on how to proceed.

(Chris Burnor) #2

What are the build errors that code above is generating? Or is it ‘building’ but not actually rendering to screen?

(David Bernado) #3

I have been trying to do pretty much the exact same thing that you are doing. I have code that generates a mesh of type nalgrebra::geometry::TriMesh, and a method that converts it into a MeshBuilder with the same vertex and index buffers.

I can tell you now that there are multiple things wrong with your code. For one, your mesh vectors need to be of types that implement the right attributes for the MeshBuilder to be able to use them. You also don’t need to call build() on your MeshBuilder when loading it, you can just use into(). It’s also worth noting that if you try to build a mesh without passing it the index buffer, it will build but not render.

Here is the code I have that loads the generated mesh:

        let mtl = world.exec(|loader: AssetLoaderSystemData<'_, Texture>| {
            loader.load_from_data(
                load_from_srgba(Srgba::new(0.0, 0.0, 1.0, 1.0)).into(),
                (),
                )
        });

        let mesh = world.exec(|loader: AssetLoaderSystemData<'_, Mesh>| {
            loader.load_from_data(
                gen.build_mesh()
                .into(),
                (),
                )
        });
        
        let _terrain = world.create_entity()
            .with(mesh)
            .with(mtl)
            .with(Transform::default())
            .build();

And here is the code for gen.build_mesh(), which does all the type conversions and MeshBuilder building:

    pub fn build_mesh(&self) -> MeshBuilder<'static> {
        let verts: Vec<PosNorm> = self.mesh.coords
            .clone()
            .into_iter()
            .map(|point| {
                let slice: [f32; 3] = point.coords.into();
                let position: Position = slice.into();
                let normal: Normal = slice.into();

                PosNorm { position, normal }
            })
            .collect();

        let mut indices: Vec<u32> = vec![];
        let _map = self.mesh.indices
            .clone()
            .unwrap_unified()
            .into_iter()
            .map(|point| {
                let slice: [u32; 3] = point.coords.into();

                for x in slice.iter() {
                    indices.push(x.clone());
                }
            });

        MeshBuilder::from(verts)
            .with_indices(indices)
    }

Now, the issue that I’m running into with this code is much more confusing. The code builds and runs, but when amethyst attempts to build the mesh it panics. Here is the backtrace:

thread '<unnamed>' panicked at 'assertion failed: `(left != right)`
  left: `0`,
 right: `0`', <::std::macros::panic macros>:5:6
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:77
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:59
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1052
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1426
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:224
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:472
  11: rust_begin_unwind
             at src/libstd/panicking.rs:380
  12: std::panicking::begin_panic_fmt
             at src/libstd/panicking.rs:334
  13: rendy_resource::buffer::Buffer<B>::create
             at ./<::std::macros::panic macros>:5
  14: rendy_factory::factory::Factory<B>::create_relevant_buffer
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rendy-factory-0.4.1/src/factory.rs:180
  15: rendy_factory::factory::Factory<B>::create_buffer
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rendy-factory-0.4.1/src/factory.rs:207
  16: rendy_mesh::mesh::MeshBuilder::build
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rendy-mesh-0.4.1/src/mesh.rs:286
  17: <amethyst_rendy::system::MeshProcessorSystem<B> as shred::system::System>::run::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/amethyst_rendy-0.5.0/src/system.rs:211
  18: amethyst_assets::storage::AssetStorage<A>::process_custom_drop::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/amethyst_assets-0.11.0/src/storage.rs:263
  19: core::result::Result<T,E>::and_then
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/result.rs:721
  20: amethyst_assets::storage::AssetStorage<A>::process_custom_drop
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/amethyst_assets-0.11.0/src/storage.rs:261
  21: amethyst_assets::storage::AssetStorage<A>::process
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/amethyst_assets-0.11.0/src/storage.rs:229
  22: <amethyst_rendy::system::MeshProcessorSystem<B> as shred::system::System>::run
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/amethyst_rendy-0.5.0/src/system.rs:206
  23: <T as shred::system::RunNow>::run_now
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/shred-0.10.2/src/system.rs:140
  24: shred::dispatch::stage::Stage::execute::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/shred-0.10.2/src/dispatch/stage.rs:111
  25: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &F>::call_mut
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/ops/function.rs:252
  26: core::iter::traits::iterator::Iterator::for_each::call::{{closure}}
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/iter/traits/iterator.rs:652
  27: core::iter::traits::iterator::Iterator::fold::ok::{{closure}}
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/iter/traits/iterator.rs:1900
  28: core::iter::traits::iterator::Iterator::try_fold
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/iter/traits/iterator.rs:1776
  29: core::iter::traits::iterator::Iterator::fold
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/iter/traits/iterator.rs:1903
  30: core::iter::traits::iterator::Iterator::for_each
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libcore/iter/traits/iterator.rs:655
  31: <rayon::iter::for_each::ForEachConsumer<F> as rayon::iter::plumbing::Folder<T>>::consume_iter
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.3.0/src/iter/for_each.rs:55
  32: rayon::iter::plumbing::Producer::fold_with
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.3.0/src/iter/plumbing/mod.rs:110
  33: rayon::iter::plumbing::bridge_producer_consumer::helper
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.3.0/src/iter/plumbing/mod.rs:438
  34: rayon::iter::plumbing::bridge_producer_consumer::helper::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.3.0/src/iter/plumbing/mod.rs:418
  35: rayon_core::join::join_context::call_a::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/join/mod.rs:125
  36: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panic.rs:318
  37: std::panicking::try::do_call
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panicking.rs:305
  38: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  39: std::panicking::try
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panicking.rs:281
  40: std::panic::catch_unwind
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panic.rs:394
  41: rayon_core::unwind::halt_unwinding
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/unwind.rs:17
  42: rayon_core::join::join_context::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/join/mod.rs:146
  43: rayon_core::registry::in_worker
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:799
  44: rayon_core::join::join_context
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/join/mod.rs:133
  45: rayon::iter::plumbing::bridge_producer_consumer::helper
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.3.0/src/iter/plumbing/mod.rs:416
  46: rayon::iter::plumbing::bridge_producer_consumer::helper::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.3.0/src/iter/plumbing/mod.rs:427
  47: rayon_core::join::join_context::call_b::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/join/mod.rs:130
  48: <rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute::call::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/job.rs:113
  49: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panic.rs:318
  50: std::panicking::try::do_call
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panicking.rs:305
  51: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  52: std::panicking::try
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panicking.rs:281
  53: std::panic::catch_unwind
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447/src/libstd/panic.rs:394
  54: rayon_core::unwind::halt_unwinding
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/unwind.rs:17
  55: <rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/job.rs:119
  56: rayon_core::job::JobRef::execute
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/job.rs:59
  57: rayon_core::registry::WorkerThread::execute
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:681
  58: rayon_core::registry::WorkerThread::wait_until_cold
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:665
  59: rayon_core::registry::WorkerThread::wait_until
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:639
  60: rayon_core::registry::main_loop
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:759
  61: rayon_core::registry::ThreadBuilder::run
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:56
  62: <rayon_core::registry::DefaultSpawn as rayon_core::registry::ThreadSpawn>::spawn::{{closure}}
             at /home/void/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.7.0/src/registry.rs:101

Amethyst seems to be having trouble processing the index buffer for the mesh, but I don’t know whether this is an issue with my code or a bug with the engine. If anyone knows what’s going on and can help, that would be greatly appreciated.