Newbie question: Access mesh data

(Michi) #1

Hi,

how can i get access of mesh data? I would like to read vertices and triangle indices.

use amethyst::{
    ecs::{
        System,
        ReadStorage,
        Join,
    },
    core::{
        Transform,
    },
    renderer::{
        MeshData,
    }
};

pub struct CollisionsSystem;

impl<'s> System<'s> for CollisionsSystem {
    type SystemData = (
        ReadStorage<'s, Transform>,
        ReadStorage<'s, MeshData>,
    );
    fn run(&mut self, ( transforms, meshes): Self::SystemData) {
        for (transform, mesh) in (&transforms, &meshes).join() {
            
            // how?

        }
    }
}

Thank you for your help :slight_smile:

0 Likes

(Joël Lupien) #2

That will work only on meshes loaded using the glTF prefab format.

This will be changed eventually so you can access all meshes, but it wasn’t made yet.

1 Like

(Michi) #3

does this mean there is no way to access 3d mesh data in systems? :frowning:

0 Likes

(Azriel Hoh) #4

Does this work:

match mesh {
    MeshData::PosTex(pos_texes) => {
        pos_texes.iter()
            .for_each(|pos_tex| {
                info!("Position {:?}", &pos_tex.position);
            });
    }
    _ => {} // See source for all the other types of vertices
}

(source)

2 Likes

(Michi) #5

Hi,

thank you for your answer. I tried printing out the vertex position with println(). it didn’t work. I don’t see any mesh data in the editor electron app too.

what i did is i imported the mesh through a prefab, wich looks like this:
#![enable(implicit_some)]
Prefab (
entities: [
(
data: (
graphics: (
mesh: Shape((shape: Sphere(32, 32),)),
material: (
albedo: Data(Rgba((1.0, 1.0, 1.0, 1.0,), (channel: Srgb),)),
),
),
transform: (),
),
),
],
)

then i load the prefab in my game.rs file like this:
type MyPrefabData = BasicScenePrefab<Vec>;

pub struct Game;

impl SimpleState for Game {
    fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) {
        let StateData { world, .. } = data;
        // Initialise the scene with a prefab
        let prefab_handle_scene = world.exec(|loader: PrefabLoader<'_, MyPrefabData>| {
            loader.load("prefab/scene.ron", RonFormat, (), ())
        });
        world
            .create_entity()
            .with(prefab_handle_scene)
            .build();

        let prefab_handle_ball = world.exec(|loader: PrefabLoader<'_, MyPrefabData>| {
            loader.load("prefab/ball.ron", RonFormat, (), ())
        });
        world
            .create_entity()
            .with(prefab_handle_ball)
            .build();
    }
}

the problem is that i don’t know where the mesh data is stored when loading the mesh through the prefab (wich in this case is just generated through Shape).

Does the data exist in a Component? Is there a “Mesh” Component with a reference to the mesh data that exists somewhere else? It’s really hard to understand what’s going on here :confused:

0 Likes

(Joël Lupien) #6

Some definitions:
MeshHandle -> pointer to the gpu memory location where the mesh is stored.
MeshData -> raw data of the mesh, like the vertices, uv coordinates, etc.

Okay so here’s what happens.

raw mesh data -> prefab -> mesh uploaded through amethyst_renderer -> you get a MeshHandle.

When this happens, you can’t get your raw mesh data back.

What I did with the gltf prefab loader is that it also
raw mesh data -> prefab -> add MeshData component to entity.

But that’s ONLY for the gltf prefab. For other prefabs, you need to change them in the engine’s source code and open a pull request.

1 Like

(Michi) #7

Hi,

thank you for your helpful answer. I tried to import a gltf file but the way i did it doesn’t work. here’s my code:

use amethyst::{
prelude::*,
assets::{
    *
},
utils::{
    scene::{
        BasicScenePrefab,
    },
},
renderer::*,
};

use amethyst_gltf::{
*,
};

type MyPrefabData = BasicScenePrefab<Vec<PosNormTex>>;
type GltfPrefabData = AssetPrefab<GltfSceneAsset, GltfSceneFormat>;

pub struct Game;

impl SimpleState for Game {
fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) {
    let StateData { world, .. } = data;
    // Initialise the scene with a prefab
    let prefab_handle_scene = world.exec(
        |loader: PrefabLoader<'_, MyPrefabData>| {
            loader.load("prefab/scene.ron", RonFormat, (), ())
        }
    );
    world
        .create_entity()
        .with(prefab_handle_scene)
        .build();

    let prefab_handle_pyramid = world.exec(
        |loader: PrefabLoader<'_, GltfPrefabData>| {
            loader.load("prefab/triangle_pyramid.ron", RonFormat, (), ())
        }
    );
    world.register::<Handle<Prefab<GltfPrefabData>>>();
    world
        .create_entity()
        .with(prefab_handle_pyramid)
        // .with(Ball::new())
        .build();
}
}

The code compiles and the engine runs but i dont see the mesh. Besides the Scene with a light and a fly camera there’s just an empty entity visible in the amethyst editor.
What am i doing wrong here?

0 Likes

(Azriel Hoh) #8

when you set up the application, and add systems (possibly in main()), do you have a PrefabLoaderSystem::<GltfPrefabData>?

That is, check that there is a PrefabLoaderSystem::<T> for every T: PrefabData

0 Likes

(Michi) #9

In my main.rs i used “GltfSceneLoaderSystem::::default()” and changed it to “PrefabLoaderSystem::::default()” and it still doesn’t work.

0 Likes

(Azriel Hoh) #10

oh they’re apparently the same thing, this is from amethyst’s source:

pub type GltfSceneLoaderSystem = PrefabLoaderSystem<GltfPrefab>;

are there any WARN or ERROR log messages that look relevant?

0 Likes

(Michi) #11

This is all i get:

[DEBUG][amethyst_assets::loader] "PREFAB": Loading asset "prefab/scene.ron" with format "Ron" from source "[default source]" (handle id: Handle { id: 0 })
[DEBUG][amethyst_assets::loader] "PREFAB": Loading asset "prefab/triangle_pyramid.ron" with format "Ron" from source "[default source]" (handle id: Handle { id: 0 })
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 0 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 1 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 2 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 3 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 4 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 5 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "renderer::Texture": Asset "<Data>" (handle id: Handle { id: 6 }) has been loaded successfully
[DEBUG][amethyst_assets::storage] "PREFAB": Asset "prefab/scene.ron" (handle id: Handle { id: 0 }) has been loaded successfully

and this is the “triangle_pyramid.ron” file:

#![enable(implicit_some)]
Prefab (
    entities: [
        (
            data: (
                graphics: (
                    mesh: Asset(File("mesh/triangle_pyramid.gltf", GltfSceneFormat, ())),
                    material: (
                        albedo: Data(Rgba((1.0, 1.0, 1.0, 1.0,), (channel: Srgb),)),
                    ),
                ),
                transform: (),
            ),
        ),
    ],
)

Is there a way to just get the data out of a gltf file and assign it to a MeshData Component and add that to an Entity? Or is asset loading bound to loading Prefabs?

0 Likes

(Joël Lupien) #12

The code in this project uses the gltf prefab and reads the mesh data https://github.com/HoppinWorld/hoppinworldclient?files=1

0 Likes

(Michi) #13

Hi everyone, i finally got the gltf loader working by copy pasting gltf example. In the System i used to print out the MeshData wich looks like this:

use amethyst::{
    ecs::{
        System,
        ReadStorage,
        Join,
    },
    core::{
        Transform,
    },
    renderer::{
        MeshData,
    }
};

pub struct CollisionsSystem;

impl<'s> System<'s> for CollisionsSystem {
    type SystemData = (
        ReadStorage<'s, Transform>,
        ReadStorage<'s, MeshData>,
    );
    fn run(&mut self, (transforms, meshes): Self::SystemData) {
        for (transform, mesh) in (&transforms, &meshes).join() {
            for join_mesh in meshes.join() {
                match join_mesh {
                    MeshData::PosNormTex(vertices) => {
                        vertices.iter()
                            .for_each(|vertex| {
                                println!("Position {:?}", &vertex.position);
                            });
                    }
                    MeshData::PosColorNorm(vertices) => {
                        vertices.iter()
                            .for_each(|vertex| {
                                println!("Position {:?}", &vertex.position);
                            });
                    }
                    MeshData::PosTex(vertices) => {
                        vertices.iter()
                            .for_each(|vertex| {
                                println!("Position {:?}", &vertex.position);
                            });
                    }
                    MeshData::PosNormTangTex(vertices) => {
                        vertices.iter()
                            .for_each(|vertex| {
                                println!("Position {:?}", &vertex.position);
                            });
                    }
                    MeshData::PosColor(vertices) => {
                        vertices.iter()
                            .for_each(|vertex| {
                                println!("Position {:?}", &vertex.position);
                            });
                    }
                    _ => {
                        println!("no matching MeshData variant");
                    }
                }
            }
        }
    }
}

i get this printed out in the console

...
no matching MeshData variant
no matching MeshData variant
no matching MeshData variant
no matching MeshData variant
...

well at least i get a MeshData Component! Thanks for your help so far, i really appreciate it :slight_smile:

0 Likes

(Azriel Hoh) #14

hm, looks like you’ve got the MeshData::Creator variant.

Creator(Box<dyn MeshCreator>)

MeshCreator#vertices() gives you a &Vec<Separate<Position>>, maybe that gives you enough info?

1 Like