norman784 / gaiku

3d agnostic framework (game engine) terrain engine
40 stars 1 forks source link

Can't see texture. Setting pixes onto the atlas not working as expected #21

Closed QuantumEntangledAndy closed 3 years ago

QuantumEntangledAndy commented 3 years ago

So after getting passed my issue in #20 I failed to get a visibile mesh. Since I didn't reach a panic associated with an empty mesh or texture, I assume this is because I have a transparent texture mapped.

Currently I map texture like this:

let mut texture = TextureAtlas2d::new(4);
texture.set_at_index(1, [chunk.color.clone(); 4*4].to_vec());
let options = BakerOptions {
    texture: Some(texture),
    ..Default::default()
};

let mesh_gox =
    VoxelBaker::bake::<NoiseChunk, GaikuTexture2d, GaikuMesh>(&chunk, &options);

let (mesh_data, tex_data) = if let Ok(Some(mesh_gox)) = mesh_gox {
    let tex_data: TextureData = options.texture.unwrap().get_texture().into();
    (mesh_gox.into(), tex_data)
} else {
    unreachable!(); // Should always have a mesh
};

With all chunks returning 1 for the index on get

fn get(&self, x: usize, y: usize, z: usize) -> (u8, u8) {
        if self.is_air(x, y, z) {
            (0, 0)
        } else {
            (1, 1)
        }
    }

Am I misunderstanding something here about how to set the pixels on a voxel?

QuantumEntangledAndy commented 3 years ago

As I understand it

TextureAtlas2d::new(4);
QuantumEntangledAndy commented 3 years ago

Reading the code I think the index for the tile and the index of set_at_index are different things

QuantumEntangledAndy commented 3 years ago

This line here confuses me a bit

https://github.com/norman784/gaiku/blob/a2c5ca0b1d3b12a8eda85a71a7b7f9fcd1458b25/gaiku-common/src/texture.rs#L74

Surely self.texture.len() is dependent on tile_size, but tile index is independent of tile size. If tile size was 100 then the limit of self.texture.len() is COLS * tile_size * ROWS * tile_size = 2560000 but the max tile index should be 256.

QuantumEntangledAndy commented 3 years ago

I have a naive implementation that sets the pixels based on the tile index rather than just the position into the texture bytes.

pub fn set_at_index(&mut self, index: u8, pixels: Vec<[u8; 4]>) {
    // Get UV position on the tex for this index
    let xy = index_to_xy(index);
    let uv = xy_to_uv(xy);

    // Convert uv to tex xy for the origin of this blit
    let x_o = (uv.0 * self.texture.width() as f32).floor() as u32; // Convert uv to tex xy
    let y_o = (uv.1 * self.texture.height() as f32).floor() as u32; // Convert uv to tex xy

    // Get the width of the tile in texture coords so we can blit that area with the pixels
    let tile_width = (COL_SIZE * self.texture.width() as f32).floor() as u32;

    // Blit the texture's tile
    pixels.iter().enumerate().for_each(|(i, v)| {
      let (dx, dy) = (i as u32 % tile_width, i as u32 / tile_width);
      let (x, y) = (x_o + dx, y_o + dy);
      self.texture.set_pixel(x, y, *v);
    });
  }

Any comments?

QuantumEntangledAndy commented 3 years ago

using my naive implementation I have colors and visible meshes now but the normals are wrong

Screenshot 2021-01-15 at 18 03 38

Will see which normals need flipping

norman784 commented 3 years ago

I'm setting up bevy integration so I can at least check how the library works in a game engine, I have no luck running amethyst, it doesn't run in my linux, I tried the master branch but it has some breaking changes.

Once I have that running I will check your code snippet.

QuantumEntangledAndy commented 3 years ago

If bevy still doesn't run for you there's a list of engines for rust here. Maybe it would be good to find a simple one for testing.

QuantumEntangledAndy commented 3 years ago

I am suspecting something is up with the octree but I am having trouble pinning it down tho as its quite complex. Will keep going down the debugging rabbit hole

QuantumEntangledAndy commented 3 years ago

I seem to have repeating chunk sections? Have a look at this picture.

Left is before Chunkify and Texuture changes Right is after

The tree is one chunk but it seems to have repeating voxels in the z direction

Untitled

QuantumEntangledAndy commented 3 years ago

Ok so repeating on the zaxis is coming from this:

https://github.com/norman784/gaiku/blob/2e9d6d125b21358bdbf89ec68dbcf32939db725b/gaiku-common/src/chunk/chunk.rs#L17-L19

which should be z*width*height not z*width*width

fn index(&self, x: usize, y: usize, z: usize) -> usize {
    x + y * self.width as usize + z * self.width as usize * self.height as usize
  }

I've patched this as part of #24

QuantumEntangledAndy commented 3 years ago

At this point I could just flip all the normals and it would work but I'd rather find out why they need flipping

QuantumEntangledAndy commented 3 years ago

Ok so its not the normals! Its the face winding order. Amethyst uses anticlockwise while gaiku uses clockwise. I think I should reverse the order as part of the into() amethyst's MeshData

QuantumEntangledAndy commented 3 years ago

So maybe we should flip the default winding order?

norman784 commented 3 years ago

If bevy still doesn't run for you there's a list of engines for rust here. Maybe it would be good to find a simple one for testing.

Sorry, my wording maybe wasn't clear, it's with amethyst that I have issues, bevy runs just fine.

So maybe we should flip the default winding order?

  • OpenGL anticlockwise
  • Amethyst anticlockwise
  • blender anticlockwise
  • Unity clockwise

This is where we can use BakerOptions, we need to add a new option where to specify the winding order, and as default we can set as counterclockwise.

Ok so repeating on the zaxis is coming from this:

https://github.com/norman784/gaiku/blob/2e9d6d125b21358bdbf89ec68dbcf32939db725b/gaiku-common/src/chunk/chunk.rs#L17-L19

which should be z*width*height not z*width*width

fn index(&self, x: usize, y: usize, z: usize) -> usize {
    x + y * self.width as usize + z * self.width as usize * self.height as usize
  }

I've patched this as part of #24

Cool, I should start to add more tests to check more cases, I was only testing against with equal dimensions across the 3 axis.

QuantumEntangledAndy commented 3 years ago

Baker options is good but this would be game engine dependent so for Amethyst and Bevy. Should check what the Bevy is, if they are both ccw then great if not then do we make an automatic transform when we do the into() BevyMesh or AmethystMesh or not?

QuantumEntangledAndy commented 3 years ago

Also after all my changes this is what it looks like again :)

Screenshot 2021-01-16 at 18 23 01
QuantumEntangledAndy commented 3 years ago

Do you want me to add the atlas changes into a PR? I find it odd that in the texture atlas index means the tile index except when setting the pixels. I think it makes sense that the atlas works with the tiles. If you want to work with the texture directly ignoring the tiles you can just grab it from the atlas.

norman784 commented 3 years ago

Baker options is good but this would be game engine dependent so for Amethyst and Bevy. Should check what the Bevy is, if they are both ccw then great if not then do we make an automatic transform when we do the into() BevyMesh or AmethystMesh or not?

You are right, we can setup the bakers counterclockwise and document that. I would submit a PR with this change soon.

Do you want me to add the atlas changes into a PR? I find it odd that in the texture atlas index means the tile index except when setting the pixels. I think it makes sense that the atlas works with the tiles. If you want to work with the texture directly ignoring the tiles you can just grab it from the atlas.

I would appreciate that, yeah my bad, it seems that I didn't pay too much attention when I worked on that. Also if you can add some basic test it will be cool.

norman784 commented 3 years ago

Is this issue solved? I think there are other issues with the texture right now, see #27 but they might are related with the mesh and not the texture.