Reading mesh data

(Will Crichton) #1

Similar to this question, I need to read the mesh data from gLTF assets. However, since that question, it seems the asset system has changed and the answer is outdated.

My specific usecase is that I need to load the meshes once, immediately after they’re loaded, in order to attach an nphysics component to their entities based on the triangle mesh data. What is the best way to do that today?

(Azriel Hoh) #2

Heya! The short version, it’s not possible with amethyst / underlying libraries’ current code.

I tried to grab the mesh data in this application, and though it’s possible get hold of the loaded GLTF, the public interface lets one get hold of a rendy::Mesh. This stores the mesh data in a buffer deep down in graphics land, and the only way to get the vertex data back out is to ask it to write it into its own type. Joy.

The GltfSceneLoaderSystem (which is a PrefabLoaderSystem under the hood) processes the GltfPrefab's MeshBuilder into the Mesh, so perhaps the way forward is:

  • Don’t include that system in the dispatcher (or at least, don’t allow it to run)
  • Load the GltfPrefab first, which should keep the mesh: MeshBuilder around with the RawVertices, and… ah it’s private.

Perhaps it’s easier to make Mesh::get_vertex_iter pub and figure out how to extract the data from there.

1 Like
(Azriel Hoh) #3

Hold on, there’s a better way where you can get the meshes and primitives! I haven’t yet got a spare moment to figure out the code, but may do tonight :v:

2 Likes
(Azriel Hoh) #4

Heya, I’ve gotten meshme to print out the gltf bounding boxes. I’m not sure how to extract the triangle mesh data, but I’m guessing it’s possible to figure that out by looking at the importer code / understanding the GLTF format.

Bounds { min: [-1.432081, -0.10525745, -3.101543], max: [1.4320809, 2.4249167, 3.4234338] }
Bounds { min: [-2.7523186, -0.74727446, -4.4910116], max: [2.7523186, 2.996406, 0.721574] }
(Will Crichton) #5

Thanks for figuring that out! That’s a great headstart. I’ll take a look at gLTF to keep going.

(Taylor Gerpheide) #6

I haven’t taken a look at azriel’s example yet, but I’m in a similar position where I’ve been struggling to get a list of vertices/indices for generating navmeshes and collider type objects so please update this if any more progress is made! I had been playing around with outputting the indices and positions from https://github.com/amethyst/amethyst/blob/master/amethyst_gltf/src/format/mesh.rs#L53 which got me something, but it seemed to be rotated and/or have z/y positions swapped. I’m a bit out of my depth here.

(Taylor Gerpheide) #7

After looking at azriel’s example I stumbled across this snippet:

//! # Basic usage

//!

//! Listing the attributes of each mesh primitive in a glTF asset.

//!

//! ```

//! # fn run() -> Result<(), Box<std::error::Error>> {

//! # let gltf = gltf::Gltf::open("examples/Box.gltf")?;

//! for mesh in gltf.meshes() {

//!    println!("Mesh #{}", mesh.index());

//!    for primitive in mesh.primitives() {

//!        println!("- Primitive #{}", primitive.index());

//!        for (semantic, _) in primitive.attributes() {

//!            println!("-- {:?}", semantic);

//!        }

//!    }

//! }

//! # Ok(())

//! # }

//! # fn main() {

//! #    let _ = run().expect("runtime error");

//! # }

//! ```

//!

//! # Reader utility

//!

//! Printing the vertex positions of each primitive of each mesh in

//! a glTF asset.

//!

//! ```

//! # fn run() -> Result<(), Box<std::error::Error>> {

//! let (gltf, buffers, _) = gltf::import("examples/Box.gltf")?;

//! for mesh in gltf.meshes() {

//!    println!("Mesh #{}", mesh.index());

//!    for primitive in mesh.primitives() {

//!        println!("- Primitive #{}", primitive.index());

//!        let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));

//!        if let Some(iter) = reader.read_positions() {

//!            for vertex_position in iter {

//!                println!("{:?}", vertex_position);

//!            }

//!        }

//!    }

//! }

//! # Ok(())

//! # }

//! # fn main() {

//! #    let _ = run().expect("runtime error");

//! # }

//! ```

This seems to accomplish the vertices part and for indices I believe you can use the code from my previous link:

use gltf::mesh::util::ReadIndices;

        let indices = match reader.read_indices() {

            Some(ReadIndices::U8(iter)) => Indices::U16(iter.map(u16::from).collect()),

            Some(ReadIndices::U16(iter)) => Indices::U16(iter.collect()),

            Some(ReadIndices::U32(iter)) => Indices::U32(iter.collect()),

            None => Indices::None,

        };
2 Likes
(Will Crichton) #8

Unfortunately, the solutions y’all recommend won’t work for me. I’m currently loading gLTF files through prefabs, meaning I can’t use a second framework to re-load the gLTF file into memory as a second representation.

As far as I can tell, the only way to access the mesh data once the asset is loaded is through the rendy Mesh struct. However, that seems to be too low-level for my purposes. There’s no way to iterate over a triangle list for example.

Do I need to change the gLTF prefab loader in Amethyst to preserve the mesh data somehow?