Code Monkey home page Code Monkey logo

block-mesh-rs's Introduction

Crab Person

๐Ÿฆ€๐Ÿฆ€๐Ÿฆ€ Libraries that I maintain ๐Ÿฆ€๐Ÿฆ€๐Ÿฆ€

  • ๐Ÿ”ญ Iโ€™m currently working on real-time computational geometry in Rust
  • ๐Ÿ“ซ How to reach me: Message me on Discord @ElGatoRoboto
  • ๐Ÿ˜„ Pronouns: he/him
  • ๐Ÿ‘ Fun fact: My dog Momo is afraid of people whose eyes are mandarin oranges (๐ŸŠ __ ๐ŸŠ)

block-mesh-rs's People

Contributors

bgr360 avatar bonsairobo avatar dcz-self avatar hankjordan avatar sargunv avatar shirakawa42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

block-mesh-rs's Issues

[HELP] Voxel Chunk not Rendering.

I am trying to create a voxel game. For now I would like to just generate a single 16x16x16 chunk. I've created a script very similar to this one, https://github.com/bonsairobo/block-mesh-rs/blob/main/examples-crate/render/main.rs and it compiles but it doesn't render.

Here's some of the code:

fn main() -> () {
    let mut app = App::new();
    app.insert_resource(Msaa {samples : 4});
    app.insert_resource(WindowDescriptor {
        title  : String::from("Voxel Test"),
        width  : 1024.0,
        height : 600.0,
        ..Default::default()
    });
    app.add_plugins(DefaultPlugins);
    app.add_startup_system(game::update_chunks);
    app.run();
}

pub fn update_chunks(
    mut commands  : Commands,
    mut meshes    : ResMut<Assets<Mesh>>,
    mut materials : ResMut<Assets<StandardMaterial>>
) -> () {
    let mesh = generate_chunk([0, 0, 0]);
    commands.spawn_bundle(PbrBundle {
        mesh      : meshes.add(mesh),
        material  : materials.add(Color::rgb(1.0, 0.9, 0.9).into()),
        transform : Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
        ..Default::default()
    });
}

type ChunkSize = block_mesh::ndshape::ConstShape3u32<16, 16, 16>;

pub fn generate_chunk(position : [i32; 3]) -> Mesh {
    let generator = FlatGenerator {};
    let size        = ChunkSize::ARRAY;
    let chunk_array = generator.generate_chunk(position, [
        position[0] * (size[0] as i32),
        position[1] * (size[1] as i32),
        position[2] * (size[2] as i32)
    ]); // Returns a `ChunkArray<'l>` object I made
    let mesh        = chunk_array.as_mesh();
    return mesh;

}

impl<'l> ChunkArray<'l> {
    pub fn as_mesh(&self) -> Mesh {
        let mut samples = [voxels::EMPTY; ChunkSize::SIZE as usize];
        for i in 0..ChunkSize::SIZE {
            let [x, y, z] = ChunkSize::delinearize(i);
            samples[i as usize] = self.array[x as usize][y as usize][z as usize].clone();
        }
        let faces = RIGHT_HANDED_Y_UP_CONFIG.faces;
        let mut buffer = GreedyQuadsBuffer::new(samples.len());
        greedy_quads(
            &samples,
            &ChunkSize {},
            [0; 3],
            [ChunkSize::ARRAY[0], ChunkSize::ARRAY[1], ChunkSize::ARRAY[2]],
            &faces,
            &mut buffer
        );
        let     num_indices  = buffer.quads.num_quads() * 6;
        let     num_vertices = buffer.quads.num_quads() * 4;
        let mut indices      = Vec::with_capacity(num_indices);
        let mut positions    = Vec::with_capacity(num_vertices);
        let mut normals      = Vec::with_capacity(num_vertices);
        for (group, face) in buffer.quads.groups.into_iter().zip(faces.into_iter()) {
            for quad in group.into_iter() {
                indices   .extend_from_slice( &face.quad_mesh_indices   (positions.len() as u32) );
                positions .extend_from_slice( &face.quad_mesh_positions (&quad, 1.0)             );
                normals   .extend_from_slice( &face.quad_mesh_normals   ()                       );
            }
        }
        let mut render_mesh = Mesh::new(PrimitiveTopology::TriangleList);
        render_mesh.set_attribute(
            "Vertex_Position",
            VertexAttributeValues::Float32x3(positions),
        );
        render_mesh.set_attribute("Vertex_Normal", VertexAttributeValues::Float32x3(normals));
        render_mesh.set_attribute(
            "Vertex_Uv",
            VertexAttributeValues::Float32x2(vec![[0.0; 2]; num_vertices]),
        );
        render_mesh.set_indices(Some(Indices::U32(indices.clone())));
        return render_mesh;
    }

Compute Task Pool panicked at attempt to add with overflow - github build

Hello!

I was using the block mesh library directly from github using block-mesh = {git = "https://github.com/bonsairobo/block-mesh-rs"} in my Cargo.toml file.

Problem: i get the error thread 'Compute Task Pool (5)' panicked at 'attempt to add with overflow', /home/yairama/.cargo/git/checkouts/block-mesh-rs-d08695c2c9849c77/71aa5de/src/greedy/merge_strategy.rs:71:28 (the compute task pool number varies for each build)

the error is generated by the greedy_quads funcion:

greedy_quads( &voxels, &ChunkShape {}, [0; 3], [CHUNK_SIZE_U32-1; 3], &faces, &mut buffer, );

(ChunkSize is 32 and ChunkShape is ConstShape3u32<32,32,32>

** The error only apperas with cargo run command, when i use cargo run --release it runs perfectly **
Also when i use the crate io build ( block-mesh = "0.2.0" in my Cargo.toml file ) it runs perfectly.

Benchmark build failing

Environment: M1 Max MBP w/ MacOS 12.3.1

active toolchain
----------------

stable-aarch64-apple-darwin (default)
rustc 1.60.0 (7737e0b5c 2022-04-04)

Repro steps:

git clone https://github.com/bonsairobo/block-mesh-rs
cd block-mesh-rs
cargo build  # builds successfully
cd bench
cargo bench  # build fails

Errors:
CleanShot 2022-04-13 at 14 09 54@2x

[Feature request] Editing a mesh

Hi, thanks a lot for your crate. Do you think you could add a function to modify the VertexAttributeValues to edit a specific face ?
This would be useful to update the meshes when it changes after its creation.

Getting a quad's color

I'm writing a little Minecraft importer for Godot and I'm using this library to convert a voxel grid into a mesh. Everything seems to work fine but I have one little issue. It seems I can't figure out how to determine which color a quad should be. My code is the following (with some details removed):

//after running greedy_mesh()...

let num_indices = quads_buffer.quads.num_quads() * 6;
let num_vertices = quads_buffer.quads.num_quads() * 4;
let mut indices = Vec::with_capacity(num_indices);
let mut positions = Vec::with_capacity(num_vertices);
let mut normals = Vec::with_capacity(num_vertices);
let mut uvcoords = Vec::with_capacity(num_vertices);
let mut colors = Vec::with_capacity(num_vertices);

for (quad_group, face) in quads_buffer.quads.groups.into_iter().zip(RIGHT_HANDED_Y_UP_CONFIG.faces) {
	for quad in &quad_group {
		indices.extend_from_slice(&face.quad_mesh_indices(positions.len() as u32));
		positions.extend_from_slice(&face.quad_mesh_positions(&quad, 1.0));
		normals.extend_from_slice(&face.quad_mesh_normals());
		uvcoords.extend_from_slice(&face.tex_coords(RIGHT_HANDED_Y_UP_CONFIG.u_flip_face, true, &quad)); 
	}
}

So I was wondering... how do you get the "material index" of a quad, which determines which color it should be? (e.g. grass should have green faces, water should have blue faces, etc)

I tried something like this, using quad.minimum to get the minimum voxel a quad belongs to...

		let [x, y, z] = quad.minimum; 
		let palette_index = &blocks[(x, y, z)];
		let color = palette[palette_index];

		colors.extend_from_slice(&[color; 4]);

But that seems to be incorrect, as you can see: (the entire river should be blue, but only parts of it are)
image

Is my code incorrect?

Voxel Transparency Issue

Hi, I'm using VoxelVisibility::Translucent for voxels that have a transparent colour. However, none of the faces of the transparent voxel are returned after greedy meshing even though there are exposed sides.

Is it supposed to only ensure that occluded faces of non-transparent voxels are visible and ignores the faces of the transparent voxel?

Requiring an `[x+1, y+1, z+1]`-sized buffer is inconvenient.

It's a little unfortunate that if you have a clean 4k page of chunk data (16 * 16 * 16), you have to copy that into a slightly larger buffer before calling into the functions in this crate.

For my particular use case, I don't think this will end up being an issue, because I will likely end up storing chunk data in a compressed format, so I will have to iterate and fill a buffer anyway. But others may want to just pass in their buffers without copying them into larger ones.

I understand how supporting this could be difficult though. Have you given this any thought?

Voxel trait inflexible

visible_block_faces accepts a pre-allocated buffer of V: Voxel. This is a limitation that becomes annoying when trying to render the same data in multiple ways.

As an example, I have a voxel scene editor, and I want to have several renderings of the same data Chunk by different properties: all voxels, walls only, conduits only. If I use visible_block_faces, I need to create different types of voxels for rendering (VAll, VWall, VConduit), with 3 different Voxel implementations, one for each class of visibility. visible_block_faces needs an allocated slice of the rendering voxels, so I can't use a slice of Voxel directly, I need to convert it. But I can't feed it an iter like this: (&[V]).map(|v| VWall::from(v). I have to ::collect() any iterator before I can use it as a slice and feed it to visible_block_faces.

I think that's unnecessarily complicated, and comes with a performance hit for a relatively simple operation.

The same problem with MergeVoxel has been solved by greedy_quads_with_merge_strategy by adding a MergeStrategy trait (although that trait is overly complicated for this use case).

  1. I can see a simpler solution reusing the Voxel trait:
pub fn visible_block_faces<T, S, V>(
	    voxels: &[T],
	    voxels_shape: &S,
	    min: [u32; 3],
	    max: [u32; 3],
	    faces: &[OrientedBlockFace; 6],
	    output: &mut UnitQuadBuffer,
	) where
	    S: Shape<u32, 3>,
            V: Voxel + From<T>,
	{
// processing example: just convert on the fly
    for t in voxels:
        let v: V = t.into();
        if v.is_opaque(): ...
  1. Another possibility would be to drop the &[T] slice in favour of a lazy Map<T, F> type, which translates on the fly.

EDIT: 3. Accept A: Index<usize, Output=T>.

In either of those cases, using a newtype would end up being a no-op, leading to (presumably) no performance loss.

I'm ready to implement this, just need to consult which solution makes sense.

Voxel trait easily confused

The Voxel trait contains 2 similar functions: is_empty and is_opaque with close but opposite meanings. Most of the times I was implementing them, I wanted to copy-paste them, but that would cause one to have the completely wrong meaning. How about turning is_opaque to is_translucent?

I'm also not quite sure how is_opaque influences mesh generation, but if it means "does not prevent inner quads from showing", then "is_empty" is strictly a subset of "is_translucent", and the 3 would have been better served by an enum:

enum VoxelVisibility {
   Empty,
   Translucent,
   Opaque,
}

How does that sound?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.