An attempt at implementing a state-of-the-art Voxel DAG in Rust

Overview

VDAG

Introduction

This is an attempt at implementing a state-of-the-art compressed voxel data structure, as described in a number of papers ([PDFs] Kampe et al., 2013, Careil et al., 2020, Villanueva et al., 2017, et al.).

The file assets/torus.json is required to run the program in its current state. It is slightly to big to upload to github, and can be downloaded from here https://drububu.com/miscellaneous/voxelizer/?out=jso at maximum resolution.

Background

Voxels are a compelling method of storing geometry data in a 3d scene. Sparse Voxel structures improve the memory usage of storing voxel data by storing only present voxels, and otherwise treating every voxel as empty.

One such structure is a Sparse Voxel Octree (binary tree with 8 children at each node), which repeatedly divides a space into 8 octants (ie. 3d quadrants). Octrees also naturally provide level-of-detail benefits, because each higher layer in the tree represents 8x as many voxels, and meta-information about that set of voxels can be used to skip descending into the tree.

A Sparse Voxel Directed Acyclic Graph (SVDAG) further reduces memory usage by recursively deduping layers and storing pointers to only one instance of a leaf or node. A Symmetric SVDAG reduces memory even further by storing 3 bits of reflection data at each node, and storing only one instance of data reflected across the X-, Y-, and/or Z-axis. This can result in very impressive compression ratios, in the neighborhood of 10 voxels per bit.

Implementation Details

I have achieved a substantially less impressive 0.75 voxels per byte, though that is likely because I am only compressing millions of voxels, instead of the billions in these papers. I am also wasting considerable data that I will eventually use for material information and additional compression.

Because this is experimental, the code is a bit of a mess and is stored in a single file. I periodically reorganize, but most of my focus is on exploring new approaches. This will probably remain the case until I converge on a design that is sufficiently optimal. (I should be making more frequent commits, regardless).

Rather than 8-byte usize pointers, 4-byte u32 indices into layer-vectors are used (and cast into usizes as needed). Some papers use 32-bit pointers to achieve the same result. The SSVDAG paper also uses indices (and takes it a step further, see Future Work below), so I'm comfortable that this a a reasonable approach.

Data on the leaf nodes is stored in a 64-bit number, representing a 43 of voxel data. This is by convention, and I am unaware if a different arrangement will give better results.

I am uncertain if sparseness is still useful in these structures, as I believe the total memory usage of empty voxels after compression is quite small. A clear benefit of sparseness is during access (if a node is known to have no children, descending into the tree can be skipped for performance). Raycasting a sparse structure can be done very efficiently. The same effect is produced here by using the index u32::MAX to represent an empty node or leaf. No one else has done this, to my knowledge, and that may be for good reason.

Future Work

In order to construct larger SSVDAGs, due to RAM (ab)usage, I will need to implement a function to merge new data into an existing SSVDAG.

I have not yet tested or seen tests of the effects of adding an additional 3 bits of rotation data, each corresponding to a 90 degree rotation in X, Y, or Z. I suspect this will further reduce memory usage, as the combination of reflections and rotations should cover 6x the number of voxel-subtree orientations.

I will look into the relative gain from each reflection axis, as up-down reflections may be uncommon enough to abandon if that bit can be better used.

Additionally, I would like to explore translations, dilations, and inversion, but I have lower hopes there. I am very curious about the possibility of storing leaf indices higher up in the tree for 2n dilation, and using a single bit to store whether that is the case. Alternately, using that bit only to indicate a 2x dilation and skipping a single layer may be preferable. Storing a single bit to invert (swap voxels with empty voxels) the data in the subsequent node may be beneficial, but it's not clear that inverted data is common, and there may be substantial raycasting consequences. I have not yet come up with a useful approach for translations.

Indices can probably be reduced further (into u16s), but that will depend on the size and (information-theoretic) complexity of the voxel data being compressed. Static typing in Rust works against me here, and I will be exploring dynamic typing in the future. The SSVDAG paper further reduces index size by storing the index of the most common ~2^n nodes in n bits. Rust may make this prohibitively difficult (but we'll see).

Material information is not yet implemented (and probably won't be until I write some raycasting with which to test it). There are several established approaches to this, and I am yet not sure which ones will be optimal for my use-case.

When I get around to developing a scene for GroundhogGame, my intention is to use the compression method to my advantage, reusing similar geometry when possible.

You might also like...
clone of grep cli written in Rust. From Chapter 12 of the Rust Programming Language book

minigrep is a clone of the grep cli in rust Minigrep will find a query string in a file. To test it out, clone the project and run cargo run body poem

Rust-blog - Educational blog posts for Rust beginners

pretzelhammer's Rust blog 🦀 I write educational content for Rust beginners and Rust advanced beginners. My posts are listed below in reverse chronolo

The ray tracer challenge in rust - Repository to follow my development of
The ray tracer challenge in rust - Repository to follow my development of "The Raytracer Challenge" book by Jamis Buck in the language Rust

The Ray Tracer Challenge This repository contains all the code written, while step by implementing Ray Tracer, based on the book "The Ray Tracer Chall

Learn-rust-the-hard-way - "Learn C The Hard Way" by Zed Shaw Converted to Rust

Learn Rust The Hard Way This is an implementation of Zed Shaw's Learn X The Hard Way for the Rust Programming Language. Installing Rust TODO: Instruct

Learn to write Rust procedural macros [Rust Latam conference, Montevideo Uruguay, March 2019]
Learn to write Rust procedural macros [Rust Latam conference, Montevideo Uruguay, March 2019]

Rust Latam: procedural macros workshop This repo contains a selection of projects designed to learn to write Rust procedural macros — Rust code that g

The Rust Compiler Collection is a collection of compilers for various languages, written with The Rust Programming Language.

rcc The Rust Compiler Collection is a collection of compilers for various languages, written with The Rust Programming Language. Compilers Language Co

Integra8 rust integration test framework Rust with a focus on productivity, extensibility, and speed.

integra8 Integra8 rust integration test framework Rust with a focus on productivity, extensibility, and speed. | This repo is in a "work in progress"

Neofetch but in Rust (rust-toml-fetch)
Neofetch but in Rust (rust-toml-fetch)

rtfetch Configuration Recompile each time you change the config file logo = "arch.logo" # in src/assets. info = [ "", "", "yellow{host_n

Rust Sandbox [code for 15 concepts of Rust language]

Rust-Programming-Tutorial Rust Sandbox [code for 15 concepts of Rust language]. The first time I've been introduced to Rust was on January 2022, you m

Owner
SamCasavant
SamCasavant
A webring of people who make cool stuff. technology, music, art, writing, anything goes!

a webring of people who make cool stuff. technology, music, art, writing, anything goes!

Kognise 44 Dec 6, 2022
An attempt to start documenting the rust sdk for temporal and how to use it following some of the examples in typescript

This is an attempt to start documenting the rust sdk for temporal and how to use it following some of the examples in typescript.

Cosm 5 May 24, 2023
Rust crate implementing short & stable ids based on timestamps

Lexicoid Short & stable IDs based on timestamps. Heavily inspired by Short, friendly base32 slugs from timestamps by @brandur. Install Install with ca

Luciano Mammino 6 Jan 29, 2023
Macro for fast implementing serialize methods in serde::Serializer trait

impl_serialize! This library provides a simple procedural macro for fast implementing serialize methods in serde::Serializer trait. [dependencies] imp

Eduard Baturin 2 Sep 6, 2022
VR Lighthouse power state management in Rust

Lighthouse VR Lighthouse power state management in Rust Windows and Linux binaries available here Usage SteamVR v1: lighthouse [on|off] [BSID] lightho

Shayne Hartford 24 Dec 21, 2022
Leetcode Solutions in Rust, Advent of Code Solutions in Rust and more

RUST GYM Rust Solutions Leetcode Solutions in Rust AdventOfCode Solutions in Rust This project demostrates how to create Data Structures and to implem

Larry Fantasy 635 Jan 3, 2023
Simple autoclicker written in Rust, to learn the Rust language.

RClicker is an autoclicker written in Rust, written to learn more about the Rust programming language. RClicker was was written by me to learn more ab

null 7 Nov 15, 2022
Rust programs written entirely in Rust

mustang Programs written entirely in Rust Mustang is a system for building programs built entirely in Rust, meaning they do not depend on any part of

Dan Gohman 561 Dec 26, 2022
Rust 核心库和标准库的源码级中文翻译,可作为 IDE 工具的智能提示 (Rust core library and standard library translation. can be used as IntelliSense for IDE tools)

Rust 标准库中文版 这是翻译 Rust 库 的地方, 相关源代码来自于 https://github.com/rust-lang/rust。 如果您不会说英语,那么拥有使用中文的文档至关重要,即使您会说英语,使用母语也仍然能让您感到愉快。Rust 标准库是高质量的,不管是新手还是老手,都可以从中

wtklbm 493 Jan 4, 2023
A library for extracting #[no_mangle] pub extern "C" functions (https://docs.rust-embedded.org/book/interoperability/rust-with-c.html#no_mangle)

A library for extracting #[no_mangle] pub extern "C" functions In order to expose a function with C binary interface for interoperability with other p

Dmitrii - Demenev 0 Feb 17, 2022