Code Monkey home page Code Monkey logo

building-blocks's Introduction

building-blocks

Crates.io Docs.rs license Crates.io Discord

Building Blocks is a voxel library for real-time applications.

Project Status

This crate is in maintenance mode. I have extracted the most useful features into their own crates with fewer overall dependencies. Rather than providing generic APIs centered around a bespoke Array type, the new crates provide simpler APIs that only require slice [T] data.

The list of new crates is here: https://github.com/stars/bonsairobo/lists/my-stack

There are currently no plans to resume development on building-blocks, and users should consider migrating to the new crates. These crates will be actively maintained as their development is driven by the feldspar project.

LOD Terrain

We focus on generally useful data structures and algorithms. Features include:

  • 2D and 3D data storage
    • Array with structure-of-arrays (SoA) storage of multiple data channels per spatial dimension
    • ChunkTree is a quadtree (2D) or octree (3D) with generic chunks and chunk storage
    • ChunkDb for compressed, persistent voxel worlds, backed by the sled embedded database
  • level of detail
    • ChunkDownsampler trait controls how new samples are generated from LOD N into LOD N+1
    • ChunkTree can act as a clipmap for keeping high detail close to a focal point, generating events to trigger:
      • chunk generation / loading
      • chunk split / merge when desired sample rate changes
      • chunk eviction
  • mesh generation
    • Surface Nets isosurface extraction
    • Minecraft-style greedy meshing
    • height maps
  • spatial queries
    • ray and ball casting against octrees with ncollide3d
    • Amanatides and Woo ray grid traversal
    • pathfinding
  • procedural generation
    • sampling signed distance fields
    • constructive solid geometry with sdfu

Short Code Example

The code below samples a signed distance field and generates a mesh from it.

use building_blocks::{
    core::sdfu::{Sphere, SDF},
    prelude::*,
    mesh::{SurfaceNetsBuffer, surface_nets},
};

let center = Point3f::fill(25.0);
let radius = 10.0;
let sphere_sdf = Sphere::new(radius).translate(center);

let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(50));
let mut samples = Array3x1::fill_with(extent, |p| sphere_sdf.dist(Point3f::from(p)));

let mut mesh_buffer = SurfaceNetsBuffer::default();
let voxel_size = 2.0; // length of the edge of a voxel
let estimate_normals = true; // use the SDF to estimate normals instead of flat shading
surface_nets(&samples, samples.extent(), voxel_size, estimate_normals, &mut mesh_buffer);

Learning

Design and Architecture

There is a terse design doc that gives an overview of design decisions made concerning the current architecture. You might find this useful as a high-level summary of the most important pieces of code.

Docs and Examples

The current best way to learn about the library is to read the documentation and examples. For the latest stable docs, look here. For the latest unstable docs, clone the repo and run

cargo doc --open

There is plentiful documentation with examples. Take a look in the examples/ directory to see how Building Blocks can be used in real applications.

Getting Started

This library is organized into several crates. The most fundamental are:

  • core: lattice point and extent data types
  • storage: storage for lattice maps, i.e. functions defined on Z^2 and Z^3

Then you get extra bits of functionality from the others:

  • mesh: 3D mesh generation algorithms
  • search: search algorithms on lattice maps

To learn the basics about lattice maps, start with these doc pages:

Benchmarks

To run the benchmarks (using the "criterion" crate), go to the root of a crate and run cargo bench. As of version 0.5.0, all benchmark results are posted in the release notes.

Configuration

LTO

It is highly recommended that you enable link-time optimization when using building-blocks. It will improve the performance of critical algorithms like meshing by up to 2x. Just add this to your Cargo.toml:

[profile.release]
lto = "thin"

Cargo Features

Building Blocks is organized into several crates, some of which are hidden behind features, and some have features themselves, which get re-exported by the top-level crate. Some features are enabled by default. You can avoid taking unnecessary dependencies by declaring default-features = false in your Cargo.toml:

[dependencies.building-blocks]
version = "0.7"
default-features = false
features = ["foo", "bar"]

Math Type Conversions

The PointN types have conversions to/from glam, nalgebra, cgmath and mint types by enabling the corresponding feature.

Compression Backends and WASM

Chunk compression supports two backends out of the box: Lz4 and Snappy. They are enabled with the "lz4" and "snappy" features. "lz4" is the default, but it relies on a C++ library, so it's not compatible with WASM. But Snappy is pure Rust, so it can! Just use default-features = false and add "snappy" to you features list.

Chunk Databases

For persistent voxel worlds that support edits, it's useful to have an embedded database for crash-consistent save state. We've chosen to use the sled crate. When you enable the sled feature, you will get access to a ChunkDb type that supports reading and writing compressed chunk data. And because sled does not yet support incremental backups (AKA snapshots), we've also implemented our own snapshot scheme in a separate sled-snapshots crate which backs a VersionedChunkDb. This database schema only stores the changes (deltas) between versions, so you don't have to store an entire map in every save.

VOX Files

".VOX" files are supported via the vox-format crate. Enable the vox-format feature to get the VoxModelBuffer trait impl for Array3x1, which allows you to read VOX files directly into an array.

Images

Arrays can be converted to ImageBuffers and constructed from GenericImageViews from the image crate. Enable the image feature to expose the generic encode_image function and From<Im> where Im: GenericImageView impl.

Signed Distance Field Utilities (sdfu)

The sdfu crate provides convenient APIs for constructive solid geometry operations. By enabling this feature, the PointN types will implement the sdfu::mathtypes traits in order to be used with these APIs. The sdfu crate also gets exported under building_blocks::core::sdfu.

Development

We prioritize work according to the project board.

If you'd like to make a contribution, please first read the design philosophy and contribution guidelines.

License: MIT

building-blocks's People

Contributors

bonsairobo avatar eadf avatar implode-nz avatar indiv0 avatar jgraef avatar lemonzyy avatar malmz avatar metarmask avatar ostwilkens avatar rezural avatar schell avatar siler avatar superdump avatar t-mw avatar zicklag 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

building-blocks's Issues

no function or associated item named `from_all_compressed` found for struct `compressible_map::CompressibleMap<_, _, _, std::hash::BuildHasherDefault<fnv::FnvHasher>>` in the current scope

building_blocks_storage-0.2.0\src\chunk_map.rs:467:41
|
467 | chunks: CompressibleFnvMap::from_all_compressed(params, all_compressed),
| ^^^^^^^^^^^^^^^^^^^ function or associated item not found in compressible_map::CompressibleMap<_, _, _, std::hash::BuildHasherDefault<fnv::FnvHasher>>

error: aborting due to previous error

For more information about this error, try rustc --explain E0599.
error: could not compile building_blocks_storage.dHasherDefaultfnv::FnvHasher>`

When trying to build with 0.2

WASM support?

First off - thank you for this crate!

When building for WASM I run into the following error:

error: failed to run custom build command for `lz4-sys v1.9.2`

Caused by:
  process didn't exit successfully: `/xxxxxxx/target/debug/build/lz4-sys-45650fce57a5b4fe/build-script-build` (exit code: 1)
  --- stdout
  TARGET = Some("wasm32-unknown-unknown")
  HOST = Some("x86_64-unknown-linux-gnu")
  CC_wasm32-unknown-unknown = None
  CC_wasm32_unknown_unknown = None
  TARGET_CC = None
  CC = None
  CFLAGS_wasm32-unknown-unknown = None
  CFLAGS_wasm32_unknown_unknown = None
  TARGET_CFLAGS = None
  CFLAGS = None
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("true")
  running: "clang" "-O3" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "--target=wasm32-unknown-unknown" "-Wall" "-Wextra" "-o" "/xxxxxx/wasm32-unknown-unknown/debug/build/lz4-sys-b5586b91058cef1c/out/liblz4/lib/lz4.o" "-c" "liblz4/lib/lz4.c"

  --- stderr


  error occurred: Failed to find tool. Is `clang` installed?

My guess is that we would have to replace the lz4-sys crate with pure Rust implementation?

[Question] Is Array Indexing Unsafe in Release Mode?

Hey there! I was looking into this library and I found this line in the docs:

Indexing assumes that the coordinates are in-bounds of the array, panicking otherwise. Bounds checking is only enabled in debug mode.

I was wondering what that meant would happen when indexing out-of-bounds on release builds. Would indexing out-of-bounds be unsafe in release builds?

Multiresolution surface nets

I know this is planned, but I have an idea on how to do this that I like to share, although I haven't managed to implement it myself.

A cheap trick I found to work with marching cubes is skirts.
It works by simply running marching squares on the faces of the chunk, and then making an extra quad if the cell the face belongs to is active, resulting in something that looks like this:
image

It's not perfect, but it hides the edges quite well for what it is, especially if the skirts have the same normal as the face they are attached to.

My idea was to adapt this to surface nets as well
I haven't managed to get this working however.
Running 2d surface nets on the chunk faces doesn't work 100%, because it misses the chunk corners, and I haven't managed to get the regular 3d surface nets connected to the face either.

How to migrate to bonsairobo/my-stack?

Hello,

could you give some pointers on how to migrate to the new stack?

I used building-blocks in my project some time ago, and now I'm wondering how to migrate to bonsairobo/my-stack. I'm not sure what is the best way to do that, and I'm not very familiar with some concepts, such as localize_points_array . I don't even know which crates to use.

Here are some of the structs, impls and functions I use. I mostly just use building_blocks to generate grids and iterate through them.

  • PointN (ilattice?)
  • Extent2i::from_min_and_shape, Extent3i::from_min_and_shape (ilattice)
  • Extent3i::from_min_and_max (ilattice)
  • Array2x1::fill, Array3x1::fill
  • Array::extent
  • Point3::axis_component_mut
  • Local::localize_points_array(&Point3i::MOORE_OFFSETS)
  • Array::strides_from_local_points
  • Array::for_each

Extents and Points seem to be covered by ilattice, but what about strides? It seems like I might need ndshape-rs. And do these new libraries work with WebAssembly (Never used that before, but I'm intending to) ?

I have code like this. I don't suppose there are drop-in replacements for something like this? (Note: I'm not asking you to rewrite the code for me, I'm just putting it here so that you could give me some pointers):

        let offsets = Local::localize_points_array(&Point3i::MOORE_OFFSETS);
        let mut neighbor_strides = [Stride(0); Point3i::MOORE_OFFSETS.len()];
        self.array.strides_from_local_points(&offsets, &mut neighbor_strides);

        let mut make_surfaces = Vec::new();

        let iter_ext = Extent3i::from_min_and_max(Point3i::fill(1), arr_ext.max() - Point3i::fill(1));

        self.array.for_each(&iter_ext, |stride: Stride, value| {
            if value != NON_EMPTY {
                return;
            }

            for offset in neighbor_strides.iter() {
                let adjacent_value = self.array.get(stride + *offset);
                if adjacent_value == OUTSIDE {
                    make_surfaces.push(stride);
                    return;
                }
            }
        });

        for stride in make_surfaces {
            let val = self.array.get_mut(stride);
            *val = SURFACE;
        }

Thanks

feature-gate simdnoise

Can simdnoise be feature gated in crates/utilities/Cargo.toml?

Cause it does not compile on a M1 Mac. There is a PR for it to be fixed, but it's getting old : verpeteren/rust-simd-noise#34

When I try to run cargo test on my M1 I get hundreds of errors like this:

323 | #[target_feature(enable = "sse4.1")]
        |              ^^^^^^^^^^^^^^^^^ `sse4.1` is not valid for this target```

Snappy/Lz4 should derive Deserialize and Serialize

I am trying to switch to Snappy (to run as wasm). I have:

      let map: SerializableChunkMap<[i32; 3], f32, (), Snappy> =
        bincode::deserialize(&terrain_res.data[..]).unwrap();

Am getting this error:

error[E0277]: the trait bound `building_blocks::prelude::Snappy: Deserialize<'_>` is not satisfied
   --> src\terrain\terrain.rs:128:9
    |
128 |         bincode::deserialize(&terrain_res.data[..]).unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `building_blocks::prelude::Snappy`

Edit: Tested with Lz4 and same issue occurs as well.

Running `cargo run --example lod_terrain smooth` produces terrain with gaps between chunks.

๐Ÿ‘‹ Hey there!

I tried running the example and ran into some potential issues.

What happens when I run the example:
image

What I expected from the docs:
image

System Info:

OS Name	Microsoft Windows 10 Home
Version	10.0.19044 Build 19044
Other OS Description 	Not Available
OS Manufacturer	Microsoft Corporation
System Name	DESKTOP-PMARINB
System Manufacturer	Gigabyte Technology Co., Ltd.
System Model	B450 I AORUS PRO WIFI
System Type	x64-based PC
System SKU	Default string
Processor	AMD Ryzen 7 3700X 8-Core Processor, 3593 Mhz, 8 Core(s), 16 Logical Processor(s)
BIOS Version/Date	American Megatrends Inc. F50, 11/27/2019
SMBIOS Version	3.2
Embedded Controller Version	255.255
BIOS Mode	UEFI
BaseBoard Manufacturer	Gigabyte Technology Co., Ltd.
BaseBoard Product	B450 I AORUS PRO WIFI-CF
Installed Physical Memory (RAM)	32.0 GB
Total Physical Memory	32.0 GB
Available Physical Memory	744 MB
Total Virtual Memory	73.9 GB
Available Virtual Memory	7.80 GB
Page File Space	41.9 GB

Add Discord

This project seems nice; I think it should have some sort of chat (it seems Discord is generally accepted among the rust community)

[Question] Suitability For 2D Navmesh Generation

I have a use-case where I need to generate a 2D navigation mesh for a non-voxel game. Currently I have a mesh that looks like this ( pardon the green line and paused icon ):

image

The issue I have is that the navigation mesh is way higher resolution than it needs to be. Those great swaths of terain with no obstacles in them are represented by many more triangles than necessary.

I noticed in your voxel meshing example, the example seems to optimize the mesh properly for the areas that are solid surfaces, not using more triangles than necessary:

image

Looking at the greedy_quads algorithm, though, it only takes a 3D voxel array.

Do you think this is a proper use-case for building-blocks and if so, do you think we could make the greedy_quads function generic over 2D and 3D or else make a 2D version? Or is there a simple way for me to convert my 2D data to 3D before feeding it to greedy quads, andthen only taking the quads that I want out of it to get a 2D surface?

Thoughts on astar?

Hello! I've really been enjoying using this library so far. Was looking at the pathfinding algorithms and noticed building-blocks doesn't have astar yet. Is that something you're interested in including? If so, I'd be open to working on integrating it from pathfinding.

Broken Links in Documentation

Just a heads up: the links to 'access traits' and 'chunk map' under 'Getting Started' on the main docs.rs page lead to unavailable resources. Also the page is titled 'Crate building_blocks', but the crate is actually called 'building-blocks'; I don't know if this is a limitation of docs.rs, an issue with this project, or my own misunderstanding, but I did take a couple minutes figuring out why my Cargo.toml wasn't working so I figured it was worth mentioning.

Edit: I see that the links have been fixed in this repository already, sorry.

`surface_nets` lighting artifacts from normal interpolation

mesh_acne

It seems like there are two issues contributing to the artifacts:

  1. Non-manifold complexes
  2. Interpolation between "unlit" normals and "lit" normals

When you see random isolated black spots that seem like they should be lit, it's because the vertex is actually non-manifold, and its normal was estimated to point more in the "unlit" direction than the "lit" direction.

Then the interpolation will make that darkness bleed out where it might not makes sense. In particular, on sharp edges. If the normal is estimated as "unlit" that will bleed around the edge.

I think the sharp edge issue is actually a bigger problem. Non-manifold complexes are always undesirable. But sharp edges are certainly something we would like to look correct.

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.