bevy_ecs_tilemap icon indicating copy to clipboard operation
bevy_ecs_tilemap copied to clipboard

Chunk (layer) visibility issue on zooming

Open nerdachse opened this issue 2 years ago • 7 comments

Hello!

I am experiencing a problem similar to that in #124. As you can see only layer 1 is experiencing this problem, not the fully filled layer 0.

https://user-images.githubusercontent.com/97800396/155609269-931fc7ba-c9be-4a77-ac0c-8e09643e9b8c.mp4

edit, I am very sorry, I compressed the mp4 with ffmpeg because it had over 10mb and somehow it doesn't display in firefox or chromium for me. Then I did it with an online tool, same thing. I can't play it in the browser. It works locally though, also if I download it. I know it's much to ask to download a random file from the internet.

To explain the issue in words.

When spawning an OrthographicBundle and having the Scale on 0.25 like so:

    let mut cam_bundle = OrthographicCameraBundle::new_2d();
    cam_bundle.orthographic_projection.scale = 0.25;
    commands.spawn_bundle(cam_bundle).insert(MainCamera);

and having a system like this to change the zoom level:

pub fn zoom_camera(
    mut query: Query<(&mut OrthographicProjection, &mut Camera), With<MainCamera>>,
    keyboard_input: Res<Input<KeyCode>>,
    mut ev_scroll: EventReader<MouseWheel>,
) {
    // TODO clean this up, no need to duplicate code
    if keyboard_input.pressed(KeyCode::LControl) {
        if keyboard_input.just_pressed(KeyCode::Key0) {
            for (mut project, mut camera) in query.iter_mut() {
                project.scale = 1.0;
                camera.projection_matrix = project.get_projection_matrix();
                camera.depth_calculation = project.depth_calculation();
            }
        } else {
            let delta_zoom: f32 = ev_scroll.iter().map(|e| e.y).sum();
            if delta_zoom != 0.0 {
                for (mut project, mut camera) in query.iter_mut() {
                    project.scale -= delta_zoom * 0.1;
                    project.scale = project.scale.clamp(0.25, 2.0);

                    camera.projection_matrix = project.get_projection_matrix();
                    camera.depth_calculation = project.depth_calculation();
                }
            }
        }
    }
}

and a map like this:



pub const TILE_SIZE: f32 = 16.0;

pub fn build_tile_world(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut map_query: MapQuery,
) {
    let texture_handle = asset_server.load("images/tiles.png");
    // Create map entity and component:
    let map_entity = commands.spawn().id();
    let mut map = Map::new(0u16, map_entity);
    let map_settings = LayerSettings::new(
            MapSize(32, 32),
            ChunkSize(32, 32),
            TileSize(TILE_SIZE, TILE_SIZE),
            TextureSize(64.0, 64.0),
        );

    // Creates a new layer builder with a layer entity.
    let (mut layer_builder, _) = LayerBuilder::new(
        &mut commands,
        map_settings,
        0u16,
        0u16,
    );

    //layer_builder.set_all(TileBundle::default());
    layer_builder.set_all(TileBundle {
        tile: Tile {
            texture_index: 12,
            ..Default::default()
        },
        ..Default::default()
    });

    // Builds the layer.
    // Note: Once this is called you can no longer edit the layer until a hard sync in bevy.
    let layer_entity = map_query.build_layer(&mut commands, layer_builder, texture_handle.clone());

    // Required to keep track of layers for a map internally.
    map.add_layer(&mut commands, 0u16, layer_entity);

    let (mut layer_1_builder, _) =
        LayerBuilder::new(&mut commands, map_settings.clone(), 0u16, 0u16);

    layer_1_builder.set_tile(TilePos(40, 40),
        TileBundle {
                    tile: Tile {
                        texture_index: 5,
                        ..Default::default()
                    },
                    ..Default::default()
                },
                ).expect("failed to set tile @pos 40/40");

    let layer_1_entity = map_query.build_layer(&mut commands, layer_1_builder, texture_handle);

    map.add_layer(&mut commands, 1u16, layer_1_entity);

    // Spawn Map
    // Required in order to use map_query to retrieve layers/tiles.
    commands
        .entity(map_entity)
        .insert(map)
        //.insert(Transform::from_xyz(-128.0, -128.0, 0.0))
        .insert(Transform::from_xyz(0.0, 0.0, 0.0))
        .insert(GlobalTransform::default());
}

and the system for spawning new tiles on layer 1, beneath the mouse cursor:


pub fn mouse_click_tile(
    mut commands: Commands, 
    mut tile_query: Query<&mut Tile>,
    mut map_query: MapQuery,
    cursor_pos: Res<CursorPosition>,
    buttons: Res<Input<MouseButton>>,
) {
    let tp = &cursor_pos.tile;
    let tp_vec2: Vec2 = tp.into();

    let tp = tp_vec2.as_uvec2();
    let tp = TilePos(tp.x, tp.y);

    if let Ok(tile_entity) = map_query.get_tile_entity(tp, 0u16, 1u16) {
        if let Ok(mut tile) = tile_query.get_mut(tile_entity) {
            if buttons.pressed(MouseButton::Right) {
                if tile.texture_index == 5 {
                    tile.texture_index = 10;
                } else {
                    tile.texture_index = 5;
                }

                map_query.notify_chunk_for_tile(tp, 0u16, 1u16);
                commands.entity(tile_entity).insert(AABB::new_quad(tp_vec2, 16));
            }
        }
    } else {
        if buttons.pressed(MouseButton::Right) {
            map_query.set_tile(&mut commands, tp, Tile {..Default::default()},
                    0u16, 1u16).expect("failed to add tile");
        }
    }
}

on zoom level/orthographic scale 0.25 the chunk/tiles do not render all the time.

Could it be that the culling is off?

nerdachse avatar Feb 24 '22 21:02 nerdachse

I'm seeing the same issue with current bevy_ecs_tilemap main branch and bevy 0.6.1. The problem also occurs at a scale of 1.0, but changing the scale affects the camera translation offsets at which layers disappear.

bevy_ecs_tilemap 0.5.0 is not affected. git bisect found that the issue was introduced with commit fca08a1a5f519fa05f06379326c1fe040380a93c.

neocturne avatar Mar 03 '22 23:03 neocturne

Reverting the following change seems to help:

diff --git b/src/render/pipeline.rs a/src/render/pipeline.rs
index 53fa3775ddae..057cd0090964 100644
--- b/src/render/pipeline.rs
+++ a/src/render/pipeline.rs
@@ -445,7 +445,7 @@ pub fn queue_meshes(
                 .get_id::<DrawTilemap>()
                 .unwrap();
 
-            for (entity, layer_id, tilemap_type, image, _mesh_uniform, transform) in
+            for (entity, _, tilemap_type, image, _mesh_uniform, transform) in
                 standard_tilemap_meshes.iter()
             {
                 #[cfg(not(feature = "atlas"))]
@@ -492,7 +492,7 @@ pub fn queue_meshes(
                     entity,
                     draw_function: draw_tilemap,
                     pipeline: pipeline_id,
-                    sort_key: FloatOrd(layer_id.0 as f32),
+                    sort_key: FloatOrd(transform.translation.z as f32),
                     batch_range: None,
                 });
             }

neocturne avatar Mar 04 '22 00:03 neocturne

I use 0.5.0 of this crate and 0.6.1/0.6.0 of the Bevy crates as appropriate, and I appear to also be experiencing identical symptoms for all layers above 0. Strong chance of PEBKAC, though.

shanesveller avatar Mar 05 '22 23:03 shanesveller

I'm also seeing what looks like the same issue using the latest main build.

jakemcleman avatar Mar 26 '22 01:03 jakemcleman

I just started seeing something like this, using Bevy 0.7 and 6796c2355b75fa383fa4067443413f8bbe4a2956 (and bevy_ecs_ldtk e005863).

Still need to investigate further, but the comment implicating the use of transform.translation.z in place of layer_id is very interesting -- I wonder if the z-indexes of the layers are too close together, and the chunks can get moved behind the background color due to rounding errors after zoom? ...Guess the next thing to check is whether the chunk is actually being drawn during frames when it can't be seen.

nfagerlund avatar Apr 19 '22 17:04 nfagerlund

My issue went away as soon as I moved my camera up in Z-levels. I was too embarrassed to post about it at the time, so sorry if I could've saved another person from some anguish.

shanesveller avatar Apr 19 '22 18:04 shanesveller

Hey, I think maybe this was actually the same bug as #175 (fixed in #182 on main). I updated to 02b044b99 (and to bevy_ecs_ldtk 1d4b8e7c86de8e6007e12412beecb54f1486ee23, which adjusts a similar-looking layer z-position issue), and can no longer reproduce this. 🙌🏼 thx @Trouv!

nfagerlund avatar Apr 21 '22 18:04 nfagerlund

This should be fixed with the new API. Please open a new issue if that's not the case.

StarArawn avatar Aug 11 '22 16:08 StarArawn