tri-mesh icon indicating copy to clipboard operation
tri-mesh copied to clipboard

Is merge working correctly?

Open BrianWiz opened this issue 11 months ago • 1 comments

Hi there!

Basically I'm trying to merge two meshes together, a sphere and a cube.

I'm getting this: image

Visualization:

I am using Bevy, here's the relevant bits:

Cargo.toml:

[dependencies]
cgmath = "0.18"
three-d-asset = "0.9.2"
thiserror = "2.0.9"

[dev-dependencies]
bevy = "0.15.1"
bevy_panorbit_camera = "0.21.2"
three-d-asset = {version="0.9.2", features = ["obj"] }

Code:

use bevy::{asset::RenderAssetUsages, prelude::*, render::mesh::{Indices, PrimitiveTopology}};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(bevy_panorbit_camera::PanOrbitCameraPlugin)
        .add_systems(Startup, setup)
        .run();
}

/// set up a simple 3D scene
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // circular base
    commands.spawn((
        Mesh3d(meshes.add(Circle::new(4.0))),
        MeshMaterial3d(materials.add(Color::WHITE)),
        Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
    ));
    // light
    commands.spawn((
        PointLight {
            shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));
    // camera
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
        bevy_panorbit_camera::PanOrbitCamera::default(),
    ));

    let mut sphere = tri_mesh::Mesh::new(&three_d_asset::TriMesh::sphere(16));
    sphere.scale(2.0);
    sphere.translate(tri_mesh::vec3(0.0, 1.5, 0.0));

    let mut cube = tri_mesh::Mesh::new(&three_d_asset::TriMesh::cube());
    cube.scale(1.5);
    cube.merge_with(&sphere);

    let mesh = to_bevy_mesh(cube);
    commands.spawn((
        Mesh3d(meshes.add(mesh)),
        MeshMaterial3d(materials.add(Color::srgba(0.5, 0.5, 1.0, 1.0))),
        Transform::from_xyz(0.0, 2.0, 0.0),
    ));
}

fn to_bevy_mesh(mesh: tri_mesh::Mesh) -> Mesh {
    let mut positions = Vec::new();
    let mut normals = Vec::new();
    let mut indices = Vec::new();
    for vertex_id in mesh.vertex_iter() {
        let position = mesh.vertex_position(vertex_id);
        positions.push(Vec3::new(position.x as f32, position.y as f32, position.z as f32));

        let normal = mesh.vertex_normal(vertex_id);
        normals.push(Vec3::new(normal.x as f32, normal.y as f32, normal.z as f32));
    }

    for face_id in mesh.face_iter() {
        let (v0, v1, v2) = mesh.face_vertices(face_id);
        indices.push(*v0);
        indices.push(*v1);
        indices.push(*v2);
    }

    let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default());
    mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions);
    mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
    mesh.insert_indices(Indices::U32(indices));
    mesh
}

I've double checked and I'm pretty sure I'm grabbing the positions, normals and vertices correctly (btw, really easy to get that info, thank you!)

I'm also getting weird behavior with split. Perhaps I'm doing something wrong or missing a step?

Edit:

I also confirmed that they are positioned reasonably by using .append()

Edit 2:

It is also worth noting that I upgraded the dependencies, but I seriously doubt those are the problem.

Edit 3:

I've ruled out that it's scale and translate.

BrianWiz avatar Jan 08 '25 13:01 BrianWiz

Sorry for the late reply, I didn't have the time to investigate, but thought I owed you an answer at least.

There's unit tests for most of the functionality but the merge (and split) functionality is so complex, so it's probably no guarantee that it works. At some point I had a running example with merge where you could see the result, however, for maintainability I removed it again. So what I'm trying to say is that it might be broken completely, but probably it's just not working in your case. As I already said, it's a really complex operation, so maybe try with some different meshes, preferably simple meshes with large polygons, and see if you can get that to work.

At least, I don't think you're doing anything wrong 🙂

asny avatar Feb 28 '25 08:02 asny