├── .gitignore ├── README.md ├── custom_theme └── main.html ├── docs ├── 404.html ├── assets │ └── test_model.flvc ├── attribute_compression.html ├── css │ ├── darcula.css │ ├── extra.css │ ├── theme.css │ └── theme_extra.css ├── cuboid_extraction.html ├── dag │ └── dag.html ├── file_formats │ ├── structlang.html │ ├── vl32.html │ └── vlascii.html ├── flvc │ ├── flvc.html │ ├── flvc_optimizations.html │ ├── full_example.html │ └── results.html ├── fonts │ ├── Lato-Bold.ttf │ ├── Lato-Bold.woff2 │ ├── Lato-BoldItalic.ttf │ ├── Lato-BoldItalic.woff2 │ ├── Lato-Italic.ttf │ ├── Lato-Italic.woff2 │ ├── Lato-Regular.ttf │ ├── Lato-Regular.woff2 │ ├── RobotoSlab-Bold.woff2 │ ├── RobotoSlab-Regular.woff2 │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 ├── graphviz │ ├── acc_depth_first.dot │ ├── breadth_first.dot │ ├── dag.dot │ ├── depth_first.dot │ ├── octree.dot │ ├── octree_complete_branches.dot │ ├── octree_complete_branches_optimization.dot │ ├── octree_node_index │ ├── octree_optimization.dot │ ├── octree_serial.dot │ ├── octree_squashed.dot │ ├── render-all.sh │ ├── simple_growth.dot │ ├── test_model.dot │ ├── test_model_delta.dot │ ├── test_model_min.dot │ └── unilateral_growth.dot ├── img │ ├── cube.svg │ ├── favicon.ico │ ├── graph │ │ ├── README.txt │ │ ├── acc_depth_first.svg │ │ ├── breadth_first.svg │ │ ├── dag.svg │ │ ├── depth_first.svg │ │ ├── huffman-start.svg │ │ ├── octree.svg │ │ ├── octree_complete_branches.svg │ │ ├── octree_complete_branches_optimization.svg │ │ ├── octree_growth.svg │ │ ├── octree_node_index.svg │ │ ├── octree_optimization.svg │ │ ├── octree_serial.svg │ │ ├── octree_squashed.svg │ │ ├── simple_growth.svg │ │ ├── test_model.svg │ │ ├── test_model_delta.svg │ │ ├── test_model_min.svg │ │ └── unilateral_growth.svg │ ├── hilbert.svg │ ├── hilbert3d.gif │ ├── model │ │ ├── chessmaster3.png │ │ ├── hilbert0.png │ │ ├── hilbert1.png │ │ ├── mars_map.png │ │ ├── ragged_cluster_magica.png │ │ ├── scrapyard.png │ │ ├── spacestation.png │ │ └── test_model.png │ ├── nested_iter.svg │ ├── perlin_noise_mve.png │ ├── pipeline.svg │ ├── render-svg.sh │ ├── voxel_noise_mve.png │ ├── z_order.png │ └── z_order.svg ├── index.html ├── introduction.html ├── js │ ├── extra.js │ ├── jquery-2.1.1.min.js │ ├── mathjax_config.js │ ├── modernizr-2.8.3.min.js │ └── theme.js ├── properties.html ├── related │ ├── literature.html │ └── voxel_formats.html ├── rle │ ├── hilbert_curves.html │ ├── rle.html │ └── space_filling_curves.html ├── search.html ├── search │ ├── lunr.js │ ├── main.js │ ├── search_index.json │ └── worker.js ├── sitemap.xml ├── sitemap.xml.gz ├── statistical_tests.html ├── svo │ ├── construction.html │ ├── optimization.html │ └── svo.html └── uncompressed.html ├── mkdocs.yml └── src ├── assets └── test_model.flvc ├── attribute_compression.md ├── css ├── darcula.css └── extra.css ├── cuboid_extraction.md ├── dag └── dag.md ├── file_formats ├── structlang.md ├── vl32.md └── vlascii.md ├── flvc ├── flvc.md ├── flvc_optimizations.md ├── full_example.md └── results.md ├── graphviz ├── acc_depth_first.dot ├── breadth_first.dot ├── dag.dot ├── depth_first.dot ├── octree.dot ├── octree_complete_branches.dot ├── octree_complete_branches_optimization.dot ├── octree_node_index ├── octree_optimization.dot ├── octree_serial.dot ├── octree_squashed.dot ├── render-all.sh ├── simple_growth.dot ├── test_model.dot ├── test_model_delta.dot ├── test_model_min.dot └── unilateral_growth.dot ├── img ├── cube.svg ├── graph │ ├── README.txt │ ├── acc_depth_first.svg │ ├── breadth_first.svg │ ├── dag.svg │ ├── depth_first.svg │ ├── huffman-start.svg │ ├── octree.svg │ ├── octree_complete_branches.svg │ ├── octree_complete_branches_optimization.svg │ ├── octree_growth.svg │ ├── octree_node_index.svg │ ├── octree_optimization.svg │ ├── octree_serial.svg │ ├── octree_squashed.svg │ ├── simple_growth.svg │ ├── test_model.svg │ ├── test_model_delta.svg │ ├── test_model_min.svg │ └── unilateral_growth.svg ├── hilbert.svg ├── hilbert3d.gif ├── model │ ├── chessmaster3.png │ ├── hilbert0.png │ ├── hilbert1.png │ ├── mars_map.png │ ├── ragged_cluster_magica.png │ ├── scrapyard.png │ ├── spacestation.png │ └── test_model.png ├── nested_iter.svg ├── perlin_noise_mve.png ├── pipeline.svg ├── render-svg.sh ├── voxel_noise_mve.png ├── z_order.png └── z_order.svg ├── index.md ├── introduction.md ├── js ├── extra.js └── mathjax_config.js ├── properties.md ├── related ├── literature.md └── voxel_formats.md ├── rle ├── hilbert_curves.md ├── rle.md └── space_filling_curves.md ├── statistical_tests.md ├── svo ├── construction.md ├── optimization.md └── svo.md └── uncompressed.md /.gitignore: -------------------------------------------------------------------------------- 1 | # DIRECTORIES 2 | site/ 3 | .idea/ 4 | 5 | # FILES 6 | .directory 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # voxel-compression-docs 2 | 3 | Documentation accompanying my research project at TU Dresden. 4 | This documentation is designed to be viewed using GitHub pages. 5 | *[View the Documentation here](https://eisenwave.github.io/voxel-compression-docs/)* 6 | 7 | ## Getting Started 8 | ```sh 9 | cd docs 10 | python3 -m http.server 8000 11 | ``` 12 | -------------------------------------------------------------------------------- /custom_theme/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block footer %} 4 | 5 | {% endblock %} 6 | 7 | {% block htmltitle %} 8 | Voxel Compression 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /docs/assets/test_model.flvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/assets/test_model.flvc -------------------------------------------------------------------------------- /docs/css/darcula.css: -------------------------------------------------------------------------------- 1 | /* 2 | Darcula color scheme from the JetBrains family of IDEs 3 | */ 4 | 5 | 6 | .hljs { 7 | white-space: pre !important; 8 | display: block !important; 9 | overflow-x: auto !important; 10 | padding: 0.5em !important; 11 | background: #2b2b2b !important; 12 | color: #bababa !important; 13 | } 14 | 15 | .hljs-class, 16 | .hljs-title { 17 | color: #bababa !important; 18 | font-weight: normal !important; 19 | } 20 | 21 | .hljs-strong, 22 | .hljs-emphasis { 23 | color: #a8a8a2 !important; 24 | } 25 | 26 | .hljs-bullet, 27 | .hljs-quote, 28 | .hljs-link, 29 | .hljs-number, 30 | .hljs-regexp, 31 | .hljs-literal { 32 | color: #6896ba !important; 33 | } 34 | 35 | .hljs-code, 36 | .hljs-selector-class { 37 | color: #a6e22e !important; 38 | } 39 | 40 | .hljs-emphasis { 41 | font-style: italic !important; 42 | } 43 | 44 | .hljs-keyword, 45 | .hljs-selector-tag, 46 | .hljs-section, 47 | .hljs-attribute, 48 | .hljs-name, 49 | .hljs-variable { 50 | color: #cb7832 !important; 51 | } 52 | 53 | .hljs-params { 54 | color: #b9b9b9 !important; 55 | } 56 | 57 | .hljs-string { 58 | color: #6a8759 !important; 59 | } 60 | 61 | .hljs-subst, 62 | .hljs-type, 63 | .hljs-built_in, 64 | .hljs-builtin-name, 65 | .hljs-symbol, 66 | .hljs-selector-id, 67 | .hljs-selector-attr, 68 | .hljs-selector-pseudo, 69 | .hljs-template-tag, 70 | .hljs-template-variable, 71 | .hljs-addition { 72 | color: #e0c46c !important; 73 | } 74 | 75 | .hljs-comment, 76 | .hljs-deletion, 77 | .hljs-meta { 78 | color: #7f7f7f !important; 79 | } 80 | -------------------------------------------------------------------------------- /docs/css/extra.css: -------------------------------------------------------------------------------- 1 | .wy-side-nav-search { 2 | background-image: linear-gradient(#eb7252, #e52b49); 3 | } 4 | 5 | .icon-home { 6 | font-weight: 900 !important; 7 | } 8 | 9 | .caption-text { 10 | font-weight: bold; 11 | } 12 | 13 | /* Hide the page title in the table of contents. 14 | li.toctree-l2:first-child, li.toctree-l3:first-child { 15 | display: none; 16 | }*/ 17 | 18 | /* Reduce excessive left-padding.*/ 19 | .toctree-l4 { 20 | padding-left: 2em !important; 21 | } 22 | 23 | body { 24 | counter-reset: section; 25 | } 26 | 27 | ul.subnav { 28 | } 29 | 30 | h1 { 31 | font-size: 250%; 32 | font-weight: 900; 33 | } 34 | 35 | h2 { 36 | font-size: 175%; 37 | counter-reset: subsection; 38 | } 39 | 40 | h3 { 41 | font-size: 135%; 42 | counter-reset: subsubsection; 43 | } 44 | 45 | h5 { 46 | margin-bottom: 0.5em; 47 | } 48 | 49 | h2::before { 50 | counter-increment: section; 51 | content: counter(section) ". "; 52 | } 53 | 54 | h3::before { 55 | counter-increment: subsection; 56 | content: counter(section) "." counter(subsection) ". "; 57 | } 58 | 59 | h4::before { 60 | counter-increment: subsubsection; 61 | content: counter(section) "." counter(subsection) "." counter(subsubsection) ". "; 62 | } 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /docs/css/theme_extra.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Wrap inline code samples otherwise they shoot of the side and 3 | * can't be read at all. 4 | * 5 | * https://github.com/mkdocs/mkdocs/issues/313 6 | * https://github.com/mkdocs/mkdocs/issues/233 7 | * https://github.com/mkdocs/mkdocs/issues/834 8 | */ 9 | .rst-content code { 10 | white-space: pre-wrap; 11 | word-wrap: break-word; 12 | padding: 2px 5px; 13 | } 14 | 15 | /** 16 | * Make code blocks display as blocks and give them the appropriate 17 | * font size and padding. 18 | * 19 | * https://github.com/mkdocs/mkdocs/issues/855 20 | * https://github.com/mkdocs/mkdocs/issues/834 21 | * https://github.com/mkdocs/mkdocs/issues/233 22 | */ 23 | .rst-content pre code { 24 | white-space: pre; 25 | word-wrap: normal; 26 | display: block; 27 | padding: 12px; 28 | font-size: 12px; 29 | } 30 | 31 | /** 32 | * Fix code colors 33 | * 34 | * https://github.com/mkdocs/mkdocs/issues/2027 35 | */ 36 | .rst-content code { 37 | color: #E74C3C; 38 | } 39 | 40 | .rst-content pre code { 41 | color: #000; 42 | background: #f8f8f8; 43 | } 44 | 45 | /* 46 | * Fix link colors when the link text is inline code. 47 | * 48 | * https://github.com/mkdocs/mkdocs/issues/718 49 | */ 50 | a code { 51 | color: #2980B9; 52 | } 53 | a:hover code { 54 | color: #3091d1; 55 | } 56 | a:visited code { 57 | color: #9B59B6; 58 | } 59 | 60 | /* 61 | * The CSS classes from highlight.js seem to clash with the 62 | * ReadTheDocs theme causing some code to be incorrectly made 63 | * bold and italic. 64 | * 65 | * https://github.com/mkdocs/mkdocs/issues/411 66 | */ 67 | pre .cs, pre .c { 68 | font-weight: inherit; 69 | font-style: inherit; 70 | } 71 | 72 | /* 73 | * Fix some issues with the theme and non-highlighted code 74 | * samples. Without and highlighting styles attached the 75 | * formatting is broken. 76 | * 77 | * https://github.com/mkdocs/mkdocs/issues/319 78 | */ 79 | .rst-content .no-highlight { 80 | display: block; 81 | padding: 0.5em; 82 | color: #333; 83 | } 84 | 85 | 86 | /* 87 | * Additions specific to the search functionality provided by MkDocs 88 | */ 89 | 90 | .search-results { 91 | margin-top: 23px; 92 | } 93 | 94 | .search-results article { 95 | border-top: 1px solid #E1E4E5; 96 | padding-top: 24px; 97 | } 98 | 99 | .search-results article:first-child { 100 | border-top: none; 101 | } 102 | 103 | form .search-query { 104 | width: 100%; 105 | border-radius: 50px; 106 | padding: 6px 12px; /* csslint allow: box-model */ 107 | border-color: #D1D4D5; 108 | } 109 | 110 | /* 111 | * Improve inline code blocks within admonitions. 112 | * 113 | * https://github.com/mkdocs/mkdocs/issues/656 114 | */ 115 | .rst-content .admonition code { 116 | color: #404040; 117 | border: 1px solid #c7c9cb; 118 | border: 1px solid rgba(0, 0, 0, 0.2); 119 | background: #f8fbfd; 120 | background: rgba(255, 255, 255, 0.7); 121 | } 122 | 123 | /* 124 | * Account for wide tables which go off the side. 125 | * Override borders to avoid wierdness on narrow tables. 126 | * 127 | * https://github.com/mkdocs/mkdocs/issues/834 128 | * https://github.com/mkdocs/mkdocs/pull/1034 129 | */ 130 | .rst-content .section .docutils { 131 | width: 100%; 132 | overflow: auto; 133 | display: block; 134 | border: none; 135 | } 136 | 137 | td, th { 138 | border: 1px solid #e1e4e5 !important; /* csslint allow: important */ 139 | border-collapse: collapse; 140 | } 141 | -------------------------------------------------------------------------------- /docs/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /docs/fonts/Lato-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-Bold.woff2 -------------------------------------------------------------------------------- /docs/fonts/Lato-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-BoldItalic.ttf -------------------------------------------------------------------------------- /docs/fonts/Lato-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-BoldItalic.woff2 -------------------------------------------------------------------------------- /docs/fonts/Lato-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-Italic.ttf -------------------------------------------------------------------------------- /docs/fonts/Lato-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-Italic.woff2 -------------------------------------------------------------------------------- /docs/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /docs/fonts/Lato-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/Lato-Regular.woff2 -------------------------------------------------------------------------------- /docs/fonts/RobotoSlab-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/RobotoSlab-Bold.woff2 -------------------------------------------------------------------------------- /docs/fonts/RobotoSlab-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/RobotoSlab-Regular.woff2 -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/graphviz/acc_depth_first.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=false 4 | node [shape=circle] 5 | 6 | 1 -> 2 -> "5/3" -> "7/4" 7 | "5/3" -> "8/5" 8 | 2 -> 6 9 | 1 -> "3/7" 10 | 1 -> "4/8" -> 9 11 | } 12 | -------------------------------------------------------------------------------- /docs/graphviz/breadth_first.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=false 4 | node [shape=circle] 5 | 6 | 1 -> 2 -> 5 -> 8 7 | 5 -> 9 8 | 2 -> 6 9 | 1 -> 3 10 | 1 -> 4 -> 7 11 | } 12 | -------------------------------------------------------------------------------- /docs/graphviz/dag.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape = record] 4 | root [label="1 | 00 | 1 | 000 | 1"] 5 | 6 | b0 [label=" 1 | 00 | 1 | 0000"] 7 | b1 [label="+4"] 8 | b2 [label="000 | 1| 000 | 1"] 9 | 10 | c00 [shape=none, label=<#d13232>] 11 | c01 [shape=none, label=<#6c6e3b>] 12 | c20 [shape=none, label=<#1d6bd1>] 13 | c21 [shape=none, label=<#bd320b>] 14 | 15 | root:f0 -> b0 16 | root:f1 -> b1 17 | root:f2 -> b2 18 | b0:f0 -> c00 19 | b0:f1 -> c01 20 | b2:f0 -> c20 [weight=5] 21 | b2:f1 -> c21 [weight=5] 22 | 23 | b1 -> c20 [style=dashed] 24 | b1 -> c21 [style=dashed] 25 | } 26 | -------------------------------------------------------------------------------- /docs/graphviz/depth_first.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=false 4 | node [shape=circle] 5 | 6 | 1 -> 2 -> 3 -> 4 7 | 3 -> 5 8 | 2 -> 6 9 | 1 -> 7 10 | 1 -> 8 -> 9 11 | } 12 | -------------------------------------------------------------------------------- /docs/graphviz/octree.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape = record] 4 | root [label="1 | 00 | 1 | 000 | 1"] 5 | 6 | b0 [label=" 1 | 00 | 1 | 0000"] 7 | b1 [label="00000000"] 8 | b2 [label="000 | 1| 0000"] 9 | 10 | c00 [shape=none, label=<#d13232>] 11 | c01 [shape=none, label=<#6c6e3b>] 12 | c20 [shape=none, label=<#1d6bd1>] 13 | 14 | root:f0 -> b0 15 | root:f1 -> b1 16 | root:f2 -> b2 17 | b0:f0 -> c00 18 | b0:f1 -> c01 19 | b2:f0 -> c20 20 | } 21 | -------------------------------------------------------------------------------- /docs/graphviz/octree_complete_branches.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | // splines=false 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label=" 1 | 1 | 1 | 1| 1| 1| 1| 1"] 6 | 7 | b0 [label=" 1 | 1 | 1 | 1| 1| 1| 1| 1"] 8 | bx [label="..."] 9 | b7 [label=" 1 | 1 | 1 | 1| 1| 1| 1| 1"] 10 | 11 | c0 [shape=none, label=<#d33>] 12 | c1 [shape=none, label=<#663>] 13 | // c2 [shape=none, label=<#4ca>] 14 | // c3 [shape=none, label=<#14a>] 15 | // c4 [shape=none, label=<#000>] 16 | // c5 [shape=none, label=<#555>] 17 | cx [shape=none, label="..."] 18 | c6 [shape=none, label=<#c00>] 19 | c7 [shape=none, label=<#c05>] 20 | 21 | c70 [shape=none, label=<#16d>] 22 | c7x [shape=none, label="..."] 23 | c77 [shape=none, label=<#c82>] 24 | 25 | root:f0 -> b0 26 | root -> bx [style=bold] 27 | root:f7 -> b7 28 | 29 | b0:f0 -> c0 30 | b0:f1 -> c1 31 | // b0:f2 -> c2 32 | // b0:f3 -> c3 33 | // b0:f4 -> c4 34 | // b0:f5 -> c5 35 | // b0:f2 -> cx 36 | // b0:f3 -> cx 37 | // b0:f4 -> cx 38 | // b0:f5 -> cx 39 | b0 -> cx [style=bold] 40 | b0:f6 -> c6 41 | b0:f7 -> c7 42 | 43 | b7:f0 -> c70 44 | b7 -> c7x [style=bold] 45 | b7:f7 -> c77 46 | } 47 | -------------------------------------------------------------------------------- /docs/graphviz/octree_complete_branches_optimization.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | splines=false 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="00000000"] 6 | 7 | c00 [shape=none, label=<#d33>] 8 | c01 [shape=none, label=<#663>] 9 | c0x [shape=none, label="..."] 10 | c06 [shape=none, label=<#c00>] 11 | c07 [shape=none, label=<#c05>] 12 | 13 | cxx [shape=none, label="..."] 14 | 15 | c77 [shape=none, label=<#c82>] 16 | 17 | root -> c00 18 | root -> c01 19 | root -> c0x [style=bold] 20 | root -> c06 21 | root -> cxx 22 | root -> c07 23 | root -> c77 24 | } 25 | -------------------------------------------------------------------------------- /docs/graphviz/octree_node_index: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape=box] 4 | 5 | "**" -> "0*" 6 | "**" -> "1*" 7 | "0*" -> 00 8 | "0*" -> 01 9 | "1*" -> 10 10 | "1*" -> 11 11 | } 12 | -------------------------------------------------------------------------------- /docs/graphviz/octree_optimization.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | 6 | a [shape=none, margin=0, label=< 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
b
33 | >,fontname="monospace"] 34 | 35 | b [shape=none, margin=0, label=< 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
b
46 | >,fontname="monospace"] 47 | 48 | c [shape=square,label="b",fontname="monospace"] 49 | 50 | a -> b [style=dotted,minlen=2,fontname="monospace"] 51 | b -> c [style=dotted,minlen=2,fontname="monospace"] 52 | } 53 | -------------------------------------------------------------------------------- /docs/graphviz/octree_serial.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=spline 4 | rankdir=LR 5 | node [shape = record] 6 | 7 | root [label="{1 | 00 | 1 | 000 | 1}"] 8 | 9 | b0 [label="{ 1 | 00 | 1 | 0000}"] 10 | b1 [label="00000000"] 11 | b2 [label="{000 | 1| 0000}"] 12 | 13 | c00 [shape=none, label=<#d13232>] 14 | c01 [shape=none, label=<#6c6e3b>] 15 | c20 [shape=none, label=<#1d6bd1>] 16 | 17 | root -> b0 -> c00 -> c01 -> b1 -> b2 -> c20 [weight=100, style=invis] 18 | 19 | root:f0:n -> b0:nw 20 | root:f1:s -> b1:s 21 | root:f2:s -> b2:s 22 | b0:f0:n -> c00:n 23 | b0:f1:n -> c01:n 24 | b2:f0:n -> c20:n 25 | } 26 | -------------------------------------------------------------------------------- /docs/graphviz/octree_squashed.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape = record] 4 | root [label=" 1 | 00 | 1 | 00000000...00000000 | 1| 0000"] 5 | 6 | c00 [shape=none, label=<#d13232>] 7 | c01 [shape=none, label=<#6c6e3b>] 8 | c20 [shape=none, label=<#1d6bd1>] 9 | 10 | root:f0 -> c00 11 | root:f1 -> c01 12 | root:f2 -> c20 13 | } 14 | -------------------------------------------------------------------------------- /docs/graphviz/render-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for f in *.dot; do 4 | out="../img/graph/${f%.dot}.svg" 5 | dot "$f" -o "$out" -Tsvg 6 | done 7 | -------------------------------------------------------------------------------- /docs/graphviz/simple_growth.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | rankdir=LR 4 | 5 | source [shape=record,label="{1|3}|{0|2}",fontname="monospace"] 6 | target [shape=record,label="{|||}|{|||}|{1|3||}|{0|2||}",fontname="monospace"] 7 | 8 | source -> target [minlen=3,style=dotted] 9 | } 10 | -------------------------------------------------------------------------------- /docs/graphviz/test_model.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="1 |00 | 1 |00 | 1 | 1"] 6 | 7 | b_red [label=" 1 |0 | 1 | 1 |0 | 1 | 1 | 1"] 8 | b_gra [label=" 1| 1| 1| 1| 1| 1| 1| 1"] 9 | b_wht [label="0 | 1 |000000"] 10 | b_aqu [label=" 1 |000000 | 1"] 11 | 12 | red [shape=rectangle, label=<ffff000a>] 13 | org [shape=rectangle, label=<ffff8b33>] 14 | gra [shape=rectangle, label=<ff646464>] 15 | wht [shape=rectangle, label=<ffffffff>] 16 | grn [shape=rectangle, label=<ff33ff4c>] 17 | blu [shape=rectangle, label=<ff3373ff>] 18 | 19 | root:f0 -> b_red 20 | root:f3 -> b_gra 21 | root:f6 -> b_wht 22 | root:f7 -> b_aqu 23 | 24 | b_red:f0 -> org 25 | b_red:f2 -> red 26 | b_red:f3 -> red 27 | b_red:f5 -> org 28 | b_red:f6 -> red 29 | b_red:f7 -> red 30 | 31 | b_aqu:f0 -> grn 32 | b_aqu:f7 -> blu 33 | 34 | b_wht:f1 -> wht 35 | 36 | b_gra:f0 -> gra 37 | b_gra:f1 -> gra 38 | b_gra:f2 -> gra 39 | b_gra:f3 -> gra 40 | b_gra:f4 -> gra 41 | b_gra:f5 -> gra 42 | b_gra:f6 -> gra 43 | b_gra:f7 -> gra 44 | } 45 | -------------------------------------------------------------------------------- /docs/graphviz/test_model_delta.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="1 |00 | 1 |00 | 1 | 1| ff33000a"] 6 | 7 | b_red [label=" 1 |0 | 1 | 1 |0 | 1 | 1 | 1| 00cc0000"] 8 | b_gra [label=" 1| 1| 1| 1| 1| 1| 1| 1| 0031645a"] 9 | b_wht [label="0 | 1 |000000 | 00ccfff5"] 10 | b_aqu [label=" 1 |000000 | 1 | 00007342"] 11 | 12 | red [shape=rectangle, label=<00000000>] 13 | org [shape=rectangle, label=<00008b29>] 14 | gra [shape=rectangle, label=<00000000>] 15 | wht [shape=rectangle, label=<00000000>] 16 | grn [shape=rectangle, label=<00008c00>] 17 | blu [shape=rectangle, label=<000000b3>] 18 | 19 | root:f0 -> b_red 20 | root:f3 -> b_gra 21 | root:f6 -> b_wht 22 | root:f7 -> b_aqu 23 | 24 | b_red:f0 -> org 25 | b_red:f2 -> red 26 | b_red:f3 -> red 27 | b_red:f5 -> org 28 | b_red:f6 -> red 29 | b_red:f7 -> red 30 | 31 | b_aqu:f0 -> grn 32 | b_aqu:f7 -> blu 33 | 34 | b_wht:f1 -> wht 35 | 36 | b_gra:f0 -> gra 37 | b_gra:f1 -> gra 38 | b_gra:f2 -> gra 39 | b_gra:f3 -> gra 40 | b_gra:f4 -> gra 41 | b_gra:f5 -> gra 42 | b_gra:f6 -> gra 43 | b_gra:f7 -> gra 44 | } 45 | 46 | -------------------------------------------------------------------------------- /docs/graphviz/test_model_min.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="1 |00 | 1 |00 | 1 | 1| ff33000a"] 6 | 7 | b_red [label=" 1 |0 | 1 | 1 |0 | 1 | 1 | 1| ffff000a"] 8 | b_gra [label=" 1| 1| 1| 1| 1| 1| 1| 1| ff646464"] 9 | b_wht [label="0 | 1 |000000 | ffffffff"] 10 | b_aqu [label=" 1 |000000 | 1 | ff33734c"] 11 | 12 | red [shape=rectangle, label=<ffff000a>] 13 | org [shape=rectangle, label=<ffff8b33>] 14 | gra [shape=rectangle, label=<ff646464>] 15 | wht [shape=rectangle, label=<ffffffff>] 16 | grn [shape=rectangle, label=<ff33ff4c>] 17 | blu [shape=rectangle, label=<ff3373ff>] 18 | 19 | root:f0 -> b_red 20 | root:f3 -> b_gra 21 | root:f6 -> b_wht 22 | root:f7 -> b_aqu 23 | 24 | b_red:f0 -> org 25 | b_red:f2 -> red 26 | b_red:f3 -> red 27 | b_red:f5 -> org 28 | b_red:f6 -> red 29 | b_red:f7 -> red 30 | 31 | b_aqu:f0 -> grn 32 | b_aqu:f7 -> blu 33 | 34 | b_wht:f1 -> wht 35 | 36 | b_gra:f0 -> gra 37 | b_gra:f1 -> gra 38 | b_gra:f2 -> gra 39 | b_gra:f3 -> gra 40 | b_gra:f4 -> gra 41 | b_gra:f5 -> gra 42 | b_gra:f6 -> gra 43 | b_gra:f7 -> gra 44 | } 45 | 46 | -------------------------------------------------------------------------------- /docs/graphviz/unilateral_growth.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | rankdir=LR 4 | 5 | source [shape=record,label="{1|3}|{0|2}",fontname="monospace"] 6 | target [shape=record,label="{|||}|{|1|3|}|{|0|2|}|{|||}",fontname="monospace"] 7 | 8 | source -> target [minlen=3,style=dotted] 9 | } 10 | -------------------------------------------------------------------------------- /docs/img/cube.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/favicon.ico -------------------------------------------------------------------------------- /docs/img/graph/README.txt: -------------------------------------------------------------------------------- 1 | The files in this directory are auto-generated. 2 | Do not put user files in here! 3 | -------------------------------------------------------------------------------- /docs/img/graph/acc_depth_first.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 3/7 32 | 33 | 3/7 34 | 35 | 36 | 37 | 1->3/7 38 | 39 | 40 | 41 | 42 | 43 | 4/8 44 | 45 | 4/8 46 | 47 | 48 | 49 | 1->4/8 50 | 51 | 52 | 53 | 54 | 55 | 5/3 56 | 57 | 5/3 58 | 59 | 60 | 61 | 2->5/3 62 | 63 | 64 | 65 | 66 | 67 | 6 68 | 69 | 6 70 | 71 | 72 | 73 | 2->6 74 | 75 | 76 | 77 | 78 | 79 | 7/4 80 | 81 | 7/4 82 | 83 | 84 | 85 | 5/3->7/4 86 | 87 | 88 | 89 | 90 | 91 | 8/5 92 | 93 | 8/5 94 | 95 | 96 | 97 | 5/3->8/5 98 | 99 | 100 | 101 | 102 | 103 | 9 104 | 105 | 9 106 | 107 | 108 | 109 | 4/8->9 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /docs/img/graph/breadth_first.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 3 32 | 33 | 3 34 | 35 | 36 | 37 | 1->3 38 | 39 | 40 | 41 | 42 | 43 | 4 44 | 45 | 4 46 | 47 | 48 | 49 | 1->4 50 | 51 | 52 | 53 | 54 | 55 | 5 56 | 57 | 5 58 | 59 | 60 | 61 | 2->5 62 | 63 | 64 | 65 | 66 | 67 | 6 68 | 69 | 6 70 | 71 | 72 | 73 | 2->6 74 | 75 | 76 | 77 | 78 | 79 | 8 80 | 81 | 8 82 | 83 | 84 | 85 | 5->8 86 | 87 | 88 | 89 | 90 | 91 | 9 92 | 93 | 9 94 | 95 | 96 | 97 | 5->9 98 | 99 | 100 | 101 | 102 | 103 | 7 104 | 105 | 7 106 | 107 | 108 | 109 | 4->7 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /docs/img/graph/depth_first.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 7 32 | 33 | 7 34 | 35 | 36 | 37 | 1->7 38 | 39 | 40 | 41 | 42 | 43 | 8 44 | 45 | 8 46 | 47 | 48 | 49 | 1->8 50 | 51 | 52 | 53 | 54 | 55 | 3 56 | 57 | 3 58 | 59 | 60 | 61 | 2->3 62 | 63 | 64 | 65 | 66 | 67 | 6 68 | 69 | 6 70 | 71 | 72 | 73 | 2->6 74 | 75 | 76 | 77 | 78 | 79 | 4 80 | 81 | 4 82 | 83 | 84 | 85 | 3->4 86 | 87 | 88 | 89 | 90 | 91 | 5 92 | 93 | 5 94 | 95 | 96 | 97 | 3->5 98 | 99 | 100 | 101 | 102 | 103 | 9 104 | 105 | 9 106 | 107 | 108 | 109 | 8->9 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /docs/img/graph/huffman-start.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 14 | a 15 | 16 | a 17 | 18 | 19 | 20 | b 21 | 22 | b 23 | 24 | 25 | 26 | c 27 | 28 | c 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/img/graph/octree.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | root 14 | 15 | 1 16 | 17 | 00 18 | 19 | 1 20 | 21 | 000 22 | 23 | 1 24 | 25 | 26 | 27 | b0 28 | 29 | 1 30 | 31 | 00 32 | 33 | 1 34 | 35 | 0000 36 | 37 | 38 | 39 | root:f0->b0 40 | 41 | 42 | 43 | 44 | 45 | b1 46 | 47 | 00000000 48 | 49 | 50 | 51 | root:f1->b1 52 | 53 | 54 | 55 | 56 | 57 | b2 58 | 59 | 000 60 | 61 | 1 62 | 63 | 0000 64 | 65 | 66 | 67 | root:f2->b2 68 | 69 | 70 | 71 | 72 | 73 | c00 74 | #d13232 75 | 76 | 77 | 78 | b0:f0->c00 79 | 80 | 81 | 82 | 83 | 84 | c01 85 | #6c6e3b 86 | 87 | 88 | 89 | b0:f1->c01 90 | 91 | 92 | 93 | 94 | 95 | c20 96 | #1d6bd1 97 | 98 | 99 | 100 | b2:f0->c20 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /docs/img/graph/octree_complete_branches_optimization.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | root 14 | 15 | 00000000 16 | 17 | 18 | 19 | c00 20 | #d33 21 | 22 | 23 | 24 | root->c00 25 | 26 | 27 | 28 | 29 | 30 | c01 31 | #663 32 | 33 | 34 | 35 | root->c01 36 | 37 | 38 | 39 | 40 | 41 | c0x 42 | ... 43 | 44 | 45 | 46 | root->c0x 47 | 48 | 49 | 50 | 51 | 52 | c06 53 | #c00 54 | 55 | 56 | 57 | root->c06 58 | 59 | 60 | 61 | 62 | 63 | c07 64 | #c05 65 | 66 | 67 | 68 | root->c07 69 | 70 | 71 | 72 | 73 | 74 | cxx 75 | ... 76 | 77 | 78 | 79 | root->cxx 80 | 81 | 82 | 83 | 84 | 85 | c77 86 | #c82 87 | 88 | 89 | 90 | root->c77 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/img/graph/octree_growth.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 14 | source 15 | 16 | 1 17 | 18 | 3 19 | 20 | 0 21 | 22 | 2 23 | 24 | 25 | 26 | target 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 1 39 | 40 | 3 41 | 42 | 43 | 44 | 45 | 46 | 0 47 | 48 | 2 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | source->target 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /docs/img/graph/octree_node_index.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | ** 14 | 15 | ** 16 | 17 | 18 | 19 | 0* 20 | 21 | 0* 22 | 23 | 24 | 25 | **->0* 26 | 27 | 28 | 29 | 30 | 31 | 1* 32 | 33 | 1* 34 | 35 | 36 | 37 | **->1* 38 | 39 | 40 | 41 | 42 | 43 | 00 44 | 45 | 00 46 | 47 | 48 | 49 | 0*->00 50 | 51 | 52 | 53 | 54 | 55 | 01 56 | 57 | 01 58 | 59 | 60 | 61 | 0*->01 62 | 63 | 64 | 65 | 66 | 67 | 10 68 | 69 | 10 70 | 71 | 72 | 73 | 1*->10 74 | 75 | 76 | 77 | 78 | 79 | 11 80 | 81 | 11 82 | 83 | 84 | 85 | 1*->11 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/img/graph/octree_squashed.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | root 14 | 15 | 1 16 | 17 | 00 18 | 19 | 1 20 | 21 | 00000000...00000000 22 | 23 | 1 24 | 25 | 0000 26 | 27 | 28 | 29 | c00 30 | #d13232 31 | 32 | 33 | 34 | root:f0->c00 35 | 36 | 37 | 38 | 39 | 40 | c01 41 | #6c6e3b 42 | 43 | 44 | 45 | root:f1->c01 46 | 47 | 48 | 49 | 50 | 51 | c20 52 | #1d6bd1 53 | 54 | 55 | 56 | root:f2->c20 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/img/graph/simple_growth.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | source 14 | 15 | 1 16 | 17 | 3 18 | 19 | 0 20 | 21 | 2 22 | 23 | 24 | 25 | target 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 1 44 | 45 | 3 46 | 47 | 48 | 49 | 50 | 51 | 0 52 | 53 | 2 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | source->target 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/img/graph/unilateral_growth.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | source 14 | 15 | 1 16 | 17 | 3 18 | 19 | 0 20 | 21 | 2 22 | 23 | 24 | 25 | target 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 1 38 | 39 | 3 40 | 41 | 42 | 43 | 44 | 45 | 0 46 | 47 | 2 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | source->target 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/img/hilbert.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/img/hilbert3d.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/hilbert3d.gif -------------------------------------------------------------------------------- /docs/img/model/chessmaster3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/chessmaster3.png -------------------------------------------------------------------------------- /docs/img/model/hilbert0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/hilbert0.png -------------------------------------------------------------------------------- /docs/img/model/hilbert1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/hilbert1.png -------------------------------------------------------------------------------- /docs/img/model/mars_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/mars_map.png -------------------------------------------------------------------------------- /docs/img/model/ragged_cluster_magica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/ragged_cluster_magica.png -------------------------------------------------------------------------------- /docs/img/model/scrapyard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/scrapyard.png -------------------------------------------------------------------------------- /docs/img/model/spacestation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/spacestation.png -------------------------------------------------------------------------------- /docs/img/model/test_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/model/test_model.png -------------------------------------------------------------------------------- /docs/img/nested_iter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/img/perlin_noise_mve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/perlin_noise_mve.png -------------------------------------------------------------------------------- /docs/img/pipeline.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | I love SVG! 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/img/render-svg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$#" -lt 2 ]]; then 4 | printf "Usage: render-svg [height]\n" 5 | exit 1 6 | fi 7 | 8 | file_in="$1" 9 | file_out="$(basename "$file_in" .svg).png" 10 | 11 | width="$2" 12 | 13 | if [[ "$#" -ge 3 ]]; then 14 | height="$3" 15 | rsvg-convert -w "$width" -h "$height" "$file_in" > "$file_out" 16 | else 17 | rsvg-convert -w "$width" "$file_in" > "$file_out" 18 | fi 19 | 20 | -------------------------------------------------------------------------------- /docs/img/voxel_noise_mve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/voxel_noise_mve.png -------------------------------------------------------------------------------- /docs/img/z_order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/img/z_order.png -------------------------------------------------------------------------------- /docs/img/z_order.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 51 | 52 | 54 | 55 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/js/extra.js: -------------------------------------------------------------------------------- 1 | // disable language-auto-detection 2 | // necessary to prevent no-code markdown preformatted blocks from being highlighted 3 | hljs.configure({languages: []}); 4 | hljs.initHighlightingOnLoad(); 5 | -------------------------------------------------------------------------------- /docs/js/mathjax_config.js: -------------------------------------------------------------------------------- 1 | MathJax.Hub.Config({ 2 | config: ["MMLorHTML.js"], 3 | jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"], 4 | extensions: [], 5 | showMathMenu: true 6 | }); 7 | -------------------------------------------------------------------------------- /docs/search/main.js: -------------------------------------------------------------------------------- 1 | function getSearchTermFromLocation() { 2 | var sPageURL = window.location.search.substring(1); 3 | var sURLVariables = sPageURL.split('&'); 4 | for (var i = 0; i < sURLVariables.length; i++) { 5 | var sParameterName = sURLVariables[i].split('='); 6 | if (sParameterName[0] == 'q') { 7 | return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20')); 8 | } 9 | } 10 | } 11 | 12 | function joinUrl (base, path) { 13 | if (path.substring(0, 1) === "/") { 14 | // path starts with `/`. Thus it is absolute. 15 | return path; 16 | } 17 | if (base.substring(base.length-1) === "/") { 18 | // base ends with `/` 19 | return base + path; 20 | } 21 | return base + "/" + path; 22 | } 23 | 24 | function formatResult (location, title, summary) { 25 | return ''; 26 | } 27 | 28 | function displayResults (results) { 29 | var search_results = document.getElementById("mkdocs-search-results"); 30 | while (search_results.firstChild) { 31 | search_results.removeChild(search_results.firstChild); 32 | } 33 | if (results.length > 0){ 34 | for (var i=0; i < results.length; i++){ 35 | var result = results[i]; 36 | var html = formatResult(result.location, result.title, result.summary); 37 | search_results.insertAdjacentHTML('beforeend', html); 38 | } 39 | } else { 40 | search_results.insertAdjacentHTML('beforeend', "

No results found

"); 41 | } 42 | } 43 | 44 | function doSearch () { 45 | var query = document.getElementById('mkdocs-search-query').value; 46 | if (query.length > min_search_length) { 47 | if (!window.Worker) { 48 | displayResults(search(query)); 49 | } else { 50 | searchWorker.postMessage({query: query}); 51 | } 52 | } else { 53 | // Clear results for short queries 54 | displayResults([]); 55 | } 56 | } 57 | 58 | function initSearch () { 59 | var search_input = document.getElementById('mkdocs-search-query'); 60 | if (search_input) { 61 | search_input.addEventListener("keyup", doSearch); 62 | } 63 | var term = getSearchTermFromLocation(); 64 | if (term) { 65 | search_input.value = term; 66 | doSearch(); 67 | } 68 | } 69 | 70 | function onWorkerMessage (e) { 71 | if (e.data.allowSearch) { 72 | initSearch(); 73 | } else if (e.data.results) { 74 | var results = e.data.results; 75 | displayResults(results); 76 | } else if (e.data.config) { 77 | min_search_length = e.data.config.min_search_length-1; 78 | } 79 | } 80 | 81 | if (!window.Worker) { 82 | console.log('Web Worker API not supported'); 83 | // load index in main thread 84 | $.getScript(joinUrl(base_url, "search/worker.js")).done(function () { 85 | console.log('Loaded worker'); 86 | init(); 87 | window.postMessage = function (msg) { 88 | onWorkerMessage({data: msg}); 89 | }; 90 | }).fail(function (jqxhr, settings, exception) { 91 | console.error('Could not load worker.js'); 92 | }); 93 | } else { 94 | // Wrap search in a web worker 95 | var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); 96 | searchWorker.postMessage({init: true}); 97 | searchWorker.onmessage = onWorkerMessage; 98 | } 99 | -------------------------------------------------------------------------------- /docs/search/worker.js: -------------------------------------------------------------------------------- 1 | var base_path = 'function' === typeof importScripts ? '.' : '/search/'; 2 | var allowSearch = false; 3 | var index; 4 | var documents = {}; 5 | var lang = ['en']; 6 | var data; 7 | 8 | function getScript(script, callback) { 9 | console.log('Loading script: ' + script); 10 | $.getScript(base_path + script).done(function () { 11 | callback(); 12 | }).fail(function (jqxhr, settings, exception) { 13 | console.log('Error: ' + exception); 14 | }); 15 | } 16 | 17 | function getScriptsInOrder(scripts, callback) { 18 | if (scripts.length === 0) { 19 | callback(); 20 | return; 21 | } 22 | getScript(scripts[0], function() { 23 | getScriptsInOrder(scripts.slice(1), callback); 24 | }); 25 | } 26 | 27 | function loadScripts(urls, callback) { 28 | if( 'function' === typeof importScripts ) { 29 | importScripts.apply(null, urls); 30 | callback(); 31 | } else { 32 | getScriptsInOrder(urls, callback); 33 | } 34 | } 35 | 36 | function onJSONLoaded () { 37 | data = JSON.parse(this.responseText); 38 | var scriptsToLoad = ['lunr.js']; 39 | if (data.config && data.config.lang && data.config.lang.length) { 40 | lang = data.config.lang; 41 | } 42 | if (lang.length > 1 || lang[0] !== "en") { 43 | scriptsToLoad.push('lunr.stemmer.support.js'); 44 | if (lang.length > 1) { 45 | scriptsToLoad.push('lunr.multi.js'); 46 | } 47 | for (var i=0; i < lang.length; i++) { 48 | if (lang[i] != 'en') { 49 | scriptsToLoad.push(['lunr', lang[i], 'js'].join('.')); 50 | } 51 | } 52 | } 53 | loadScripts(scriptsToLoad, onScriptsLoaded); 54 | } 55 | 56 | function onScriptsLoaded () { 57 | console.log('All search scripts loaded, building Lunr index...'); 58 | if (data.config && data.config.separator && data.config.separator.length) { 59 | lunr.tokenizer.separator = new RegExp(data.config.separator); 60 | } 61 | 62 | if (data.index) { 63 | index = lunr.Index.load(data.index); 64 | data.docs.forEach(function (doc) { 65 | documents[doc.location] = doc; 66 | }); 67 | console.log('Lunr pre-built index loaded, search ready'); 68 | } else { 69 | index = lunr(function () { 70 | if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) { 71 | this.use(lunr[lang[0]]); 72 | } else if (lang.length > 1) { 73 | this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility 74 | } 75 | this.field('title'); 76 | this.field('text'); 77 | this.ref('location'); 78 | 79 | for (var i=0; i < data.docs.length; i++) { 80 | var doc = data.docs[i]; 81 | this.add(doc); 82 | documents[doc.location] = doc; 83 | } 84 | }); 85 | console.log('Lunr index built, search ready'); 86 | } 87 | allowSearch = true; 88 | postMessage({config: data.config}); 89 | postMessage({allowSearch: allowSearch}); 90 | } 91 | 92 | function init () { 93 | var oReq = new XMLHttpRequest(); 94 | oReq.addEventListener("load", onJSONLoaded); 95 | var index_path = base_path + '/search_index.json'; 96 | if( 'function' === typeof importScripts ){ 97 | index_path = 'search_index.json'; 98 | } 99 | oReq.open("GET", index_path); 100 | oReq.send(); 101 | } 102 | 103 | function search (query) { 104 | if (!allowSearch) { 105 | console.error('Assets for search still loading'); 106 | return; 107 | } 108 | 109 | var resultDocuments = []; 110 | var results = index.search(query); 111 | for (var i=0; i < results.length; i++){ 112 | var result = results[i]; 113 | doc = documents[result.ref]; 114 | doc.summary = doc.text.substring(0, 200); 115 | resultDocuments.push(doc); 116 | } 117 | return resultDocuments; 118 | } 119 | 120 | if( 'function' === typeof importScripts ) { 121 | onmessage = function (e) { 122 | if (e.data.init) { 123 | init(); 124 | } else if (e.data.query) { 125 | postMessage({ results: search(e.data.query) }); 126 | } else { 127 | console.error("Worker - Unrecognized message: " + e); 128 | } 129 | }; 130 | } 131 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | None 4 | 2021-01-12 5 | daily 6 | 7 | None 8 | 2021-01-12 9 | daily 10 | 11 | None 12 | 2021-01-12 13 | daily 14 | 15 | None 16 | 2021-01-12 17 | daily 18 | 19 | None 20 | 2021-01-12 21 | daily 22 | 23 | None 24 | 2021-01-12 25 | daily 26 | 27 | None 28 | 2021-01-12 29 | daily 30 | 31 | None 32 | 2021-01-12 33 | daily 34 | 35 | None 36 | 2021-01-12 37 | daily 38 | 39 | None 40 | 2021-01-12 41 | daily 42 | 43 | None 44 | 2021-01-12 45 | daily 46 | 47 | None 48 | 2021-01-12 49 | daily 50 | 51 | None 52 | 2021-01-12 53 | daily 54 | 55 | None 56 | 2021-01-12 57 | daily 58 | 59 | None 60 | 2021-01-12 61 | daily 62 | 63 | None 64 | 2021-01-12 65 | daily 66 | 67 | None 68 | 2021-01-12 69 | daily 70 | 71 | None 72 | 2021-01-12 73 | daily 74 | 75 | None 76 | 2021-01-12 77 | daily 78 | 79 | None 80 | 2021-01-12 81 | daily 82 | 83 | None 84 | 2021-01-12 85 | daily 86 | 87 | None 88 | 2021-01-12 89 | daily 90 | 91 | None 92 | 2021-01-12 93 | daily 94 | 95 | -------------------------------------------------------------------------------- /docs/sitemap.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/docs/sitemap.xml.gz -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: VOXEL COMPRESSION 2 | 3 | use_directory_urls: false 4 | 5 | docs_dir: src 6 | site_dir: docs 7 | 8 | theme: 9 | name: readthedocs 10 | highlightjs: true 11 | hljs_style: darcula 12 | hljs_languages: [asm, ebnf, cpp, rust, python] 13 | custom_dir: custom_theme 14 | 15 | markdown_extensions: 16 | - toc: 17 | toc_depth: 2 18 | - admonition 19 | - footnotes 20 | - mdx_math: 21 | enable_dollar_delimiter: true 22 | 23 | nav: 24 | - index.md 25 | - introduction.md 26 | - Basics: 27 | - properties.md 28 | - statistical_tests.md 29 | - Related Work: 30 | - related/overview.md 31 | - related/voxel_formats.md 32 | - related/literature.md 33 | - Geometry Encoding: 34 | - uncompressed.md 35 | - rle/rle.md 36 | - rle/space_filling_curves.md 37 | - rle/hilbert_curves.md 38 | - svo/svo.md 39 | - svo/construction.md 40 | - svo/optimization.md 41 | - dag/dag.md 42 | - cuboid_extraction.md 43 | - Attribute Encoding: 44 | - attribute_compression.md 45 | - Implementation: 46 | - flvc/flvc.md 47 | - flvc/flvc_optimizations.md 48 | - flvc/full_example.md 49 | - flvc/results.md 50 | - Auxiliary File Formats: 51 | - file_formats/vl32.md 52 | - file_formats/vlascii.md 53 | - file_formats/structlang.md 54 | 55 | extra_css: 56 | - css/darcula.css 57 | - css/extra.css 58 | 59 | extra_javascript: 60 | - 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_HTML' 61 | - js/mathjax_config.js 62 | - js/extra.js 63 | -------------------------------------------------------------------------------- /src/assets/test_model.flvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/assets/test_model.flvc -------------------------------------------------------------------------------- /src/attribute_compression.md: -------------------------------------------------------------------------------- 1 | # SVO Attribute Compression 2 | 3 | Geometry is the most important attribute, as it gives the model shape. 4 | A model can exist without color attributes but not without a shape. 5 | However, geometry does not inherently make up the majority of a model's 6 | information in bytes. 7 | Whether a voxel exists or not is only single-bit information, whereas color is 8 | often 24-bit information. 9 | Also consider alpha channels, weights, and many other attributes and it becomes 10 | plain to see that other attributes comprise the vast majority of information. 11 | 12 | ## Requirements 13 | 14 | We have already decided to use SVOs as the form of geometry compression. 15 | It is essential that whatever method we design, it must work well with an 16 | existing SVO structure. 17 | In total, we have the following requirements: 18 | 19 | - good SVO interoperability 20 | - low memory/time complexity when encoding/decoding models 21 | - streamability 22 | - exploiting redundancies in typical models 23 | - high compression ratio 24 | - acceptable real world performance 25 | 26 | 27 | ## Inspiration: Image-Based Approach 28 | 29 | Storing a 24-bit RGB color for every voxel would be very expensive. 30 | What some formats such as PNG instead do is store a delta between neighboring colors. 31 | Instead of storing deltas we could also store whether neighboring colors are exactly identical, but such a naive 32 | approach would become very ineffective when introducing small amounts of noise into the colors. 33 | 34 | ## Primer on PNG Filtering 35 | 36 | ```plain 37 | c|b 38 | -+- 39 | a|x 40 | ``` 41 | `x` is the color to encode and `a, b, c` are its neighbors. 42 | In the [Filtering Section](https://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters) of the PNG specification we can 43 | see that the colors are converted to a delta-based representation relative to their neighbors. 44 | 45 | This step however does not reduce the size of the data as "both the inputs and outputs fit into a byte". 46 | It is merely a pre-processing step which increases redundancy in the image bytes and thus improves 47 | [DEFLATE compression, the next step](https://www.w3.org/TR/2003/REC-PNG-20031110/#10Compression). 48 | The data will be turned into mostly low values, often times exactly zero, 49 | assuming that the deltas from the prediction are low in magnitude. 50 | 51 | ## Applying The Approach to Three Dimensions 52 | 53 | The PNG-style approach is already very promising but needs to be heavily modified 54 | so that we can apply it to 3D models. 55 | It meets all requirements in terms of performance and streamability. 56 | An added bonus is that the entropy coder can be treated as a black box and easily 57 | swapped out by a different algorithm. 58 | We are not in any way restricted to using zlib specifically. 59 | 60 | However, it is not obvious how to extend this approach to work well with an SVO. 61 | The greatest problems arise during the decoding process: 62 | 63 | 1. We might not always have a neighbor, unlike in an image where we only need to 64 | store the previous and the current line of pixels. 65 | Voxels can be surrounded by vast quantities of empty space. 66 | 2. Making it possible to access already read neighbors randomly would require 67 | reading the entire SVO into memory when decoding. 68 | 3. Random access to neighbors in an SVO would have logarithmic complexity. 69 | In an image, it would be constant. 70 | 4. We don't make any use of the hierarchical structure of the SVO when referencing 71 | direct neighbors. 72 | 73 | There is a simple solution that solves every single one of these problems: 74 | Referencing parent nodes and encoding deltas to parents instead of deltas to 75 | direct neighbors. 76 | Since every node has a parent (except for the root node) and parents are very 77 | easy to access during encoding and decoding, we resolve almost all problems 78 | regarding space/time/memory requirements. 79 | The center of parent nodes is also located half a voxel away from the center of 80 | its child nodes, which is why their attributes are typically similar. 81 | 82 | In an SVO which encodes voxel models, only the leaf nodes have any attribute values. 83 | The leaf nodes represent the voxels, all layers above are just subdivisions of space. 84 | Before we can compute a delta from the parents, we must propagate the values of 85 | children upwards in the tree in a mipmapping step. 86 | For example, the parent could be assigned the minimum, maximum, average, etc. of 87 | all its children. 88 | See the [FLVC Data Stream](flvc/flvc_optimizations.md) for how this was 89 | implemented in practice. 90 | This mipmapping step does increase the size of the model initially, but if the 91 | values of the children are all very similar, there will be a net benefit for 92 | the entropy coder. 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/css/darcula.css: -------------------------------------------------------------------------------- 1 | /* 2 | Darcula color scheme from the JetBrains family of IDEs 3 | */ 4 | 5 | 6 | .hljs { 7 | white-space: pre !important; 8 | display: block !important; 9 | overflow-x: auto !important; 10 | padding: 0.5em !important; 11 | background: #2b2b2b !important; 12 | color: #bababa !important; 13 | } 14 | 15 | .hljs-class, 16 | .hljs-title { 17 | color: #bababa !important; 18 | font-weight: normal !important; 19 | } 20 | 21 | .hljs-strong, 22 | .hljs-emphasis { 23 | color: #a8a8a2 !important; 24 | } 25 | 26 | .hljs-bullet, 27 | .hljs-quote, 28 | .hljs-link, 29 | .hljs-number, 30 | .hljs-regexp, 31 | .hljs-literal { 32 | color: #6896ba !important; 33 | } 34 | 35 | .hljs-code, 36 | .hljs-selector-class { 37 | color: #a6e22e !important; 38 | } 39 | 40 | .hljs-emphasis { 41 | font-style: italic !important; 42 | } 43 | 44 | .hljs-keyword, 45 | .hljs-selector-tag, 46 | .hljs-section, 47 | .hljs-attribute, 48 | .hljs-name, 49 | .hljs-variable { 50 | color: #cb7832 !important; 51 | } 52 | 53 | .hljs-params { 54 | color: #b9b9b9 !important; 55 | } 56 | 57 | .hljs-string { 58 | color: #6a8759 !important; 59 | } 60 | 61 | .hljs-subst, 62 | .hljs-type, 63 | .hljs-built_in, 64 | .hljs-builtin-name, 65 | .hljs-symbol, 66 | .hljs-selector-id, 67 | .hljs-selector-attr, 68 | .hljs-selector-pseudo, 69 | .hljs-template-tag, 70 | .hljs-template-variable, 71 | .hljs-addition { 72 | color: #e0c46c !important; 73 | } 74 | 75 | .hljs-comment, 76 | .hljs-deletion, 77 | .hljs-meta { 78 | color: #7f7f7f !important; 79 | } 80 | -------------------------------------------------------------------------------- /src/css/extra.css: -------------------------------------------------------------------------------- 1 | .wy-side-nav-search { 2 | background-image: linear-gradient(#eb7252, #e52b49); 3 | } 4 | 5 | .icon-home { 6 | font-weight: 900 !important; 7 | } 8 | 9 | .caption-text { 10 | font-weight: bold; 11 | } 12 | 13 | /* Hide the page title in the table of contents. 14 | li.toctree-l2:first-child, li.toctree-l3:first-child { 15 | display: none; 16 | }*/ 17 | 18 | /* Reduce excessive left-padding.*/ 19 | .toctree-l4 { 20 | padding-left: 2em !important; 21 | } 22 | 23 | body { 24 | counter-reset: section; 25 | } 26 | 27 | ul.subnav { 28 | } 29 | 30 | h1 { 31 | font-size: 250%; 32 | font-weight: 900; 33 | } 34 | 35 | h2 { 36 | font-size: 175%; 37 | counter-reset: subsection; 38 | } 39 | 40 | h3 { 41 | font-size: 135%; 42 | counter-reset: subsubsection; 43 | } 44 | 45 | h5 { 46 | margin-bottom: 0.5em; 47 | } 48 | 49 | h2::before { 50 | counter-increment: section; 51 | content: counter(section) ". "; 52 | } 53 | 54 | h3::before { 55 | counter-increment: subsection; 56 | content: counter(section) "." counter(subsection) ". "; 57 | } 58 | 59 | h4::before { 60 | counter-increment: subsubsection; 61 | content: counter(section) "." counter(subsection) "." counter(subsubsection) ". "; 62 | } 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/dag/dag.md: -------------------------------------------------------------------------------- 1 | # Directed Acyclic Graph 2 | 3 | ![Directed Acyclic Graph](../img/graph/dag.svg)
4 | *Figure 1: A Directed Acyclic Graph* 5 | 6 | Directed Acyclic Graphs (DAGs) for voxel encoding build on the idea of octrees. 7 | However, they allow nodes to reference the branches of other nodes. 8 | 9 | How this may work can be seen in *Figure 1*. 10 | The second branch of the root node stores a `+4`. 11 | This `+4` points four nodes ahead, on the same level in the graph and tells the decoder "this node has the same content" 12 | as the node four positions ahead. 13 | It is a four because there are three zero bits in the root node between this node and the one it points to. 14 | -------------------------------------------------------------------------------- /src/file_formats/structlang.md: -------------------------------------------------------------------------------- 1 | # Structure Language (StructLang) 2 | 3 | StructLang is a data specification language used within the scope of this project. 4 | It uses a syntax similar to Rust and C to mathematically specify a syntax for binary data. 5 | 6 | 7 | ## Comments 8 | 9 | Comments begin with a `//` and continue until the end of the line. 10 | Alternatively, a comment block which begins with `/*` and ends with `*/` can be used. 11 | 12 | ## Settings 13 | 14 | Some global settings may be necessary to write a proper specification. 15 | 16 | ### Syntax 17 | ```ebnf 18 | set = "set" identifier "=" value; 19 | ``` 20 | 21 | ### Examples 22 | ```rust 23 | set byte_bits = 32 24 | set default_byte_order = big_endian 25 | set default_signed_representation = twos_complement 26 | ``` 27 | 28 | ### List of Settings 29 | 30 | | Identifier | Type | Description | 31 | | ----- | ----- | ----- | 32 | | `byte_bits` | `unsigned integer` | number of bits in one byte 33 | | `default_byte_order` | `modifier ` | default byte order (endianness) of types 34 | | `default_signed_representation` | `modifier ` | default representation of signed integers 35 | 36 | ## Type Definitions 37 | 38 | Definitions define data types. 39 | 40 | ### Syntax 41 | ```ebnf 42 | def = "def" type "=" {modifier} base_type; 43 | ``` 44 | 45 | - `type` is the identifier of the type 46 | - `modifier` a type modifier 47 | - `base_type` the base type which this type is specializing 48 | 49 | ### Example 50 | ```python 51 | def i32 = signed 32_bit twos_complement integer 52 | def u8 = unsigned 8_bit integer 53 | def string = null_terminated u8[] 54 | ``` 55 | 56 | ## Arrays 57 | 58 | Arrays are blocks of one type which are stored using a single variable. 59 | 60 | ### Syntax 61 | 62 | ```ebnf 63 | array_type = type "[" size | "" "]"; 64 | ``` 65 | 66 | ### Examples 67 | 68 | ```rust 69 | u8[4096] buffer // a constant-sized array 70 | 71 | u32 size 72 | u8[size] var_buffer // a variable-sized array 73 | 74 | u8[] endless_buffer // an array which extends until the end of the data 75 | ``` 76 | 77 | ## Structures 78 | 79 | Defines a structure of other types. 80 | These types can also be structures. 81 | The first (uppermost) type in a struct is also the first element in the serialized data. 82 | 83 | ### Syntax 84 | 85 | ```ebnf 86 | struct = "struct" identifier "{" 87 | type identifier 88 | ... 89 | "}"; 90 | ``` 91 | 92 | ### Example 93 | 94 | ```rust 95 | struct Color { 96 | u8 red 97 | u8 green 98 | u8 blue 99 | } 100 | ``` 101 | 102 | ## Enumerations 103 | 104 | Defines a list of constants of some type. 105 | 106 | ### Syntax 107 | 108 | ```ebnf 109 | enum = "enum", identifier, ":", type, "{", 110 | {identifier, "=", value}, 111 | "}"; 112 | ``` 113 | 114 | ### Examples 115 | 116 | ```rust 117 | enum Size : string { 118 | SMALL = "S" 119 | MEDIUM = "M" 120 | LARGE = "L" 121 | EXTRA_LARGE = "XL" 122 | } 123 | 124 | enum ArgbColor : u32 { 125 | RED = 0xffff0000 126 | GREEN = 0xff00ff00 127 | BLUE = 0xff0000ff 128 | } 129 | ``` 130 | 131 | ## Templated Structures 132 | 133 | Sometimes a structure depends on content found in a header or other structures. 134 | Templates can change how a structure is laid out using variables. 135 | 136 | ### Syntax 137 | 138 | ```ebnf 139 | struct = "struct" type "<" type {identifier ","} ">" "{" 140 | ... 141 | "}"; 142 | ``` 143 | 144 | ### Example 145 | 146 | ```rust 147 | struct varint { 148 | if bits == 8 { 149 | u8 data 150 | } 151 | else if bits == 16 { 152 | u16 data 153 | } 154 | else if bits == 32 { 155 | u32 data 156 | } 157 | else { 158 | error "Invalid bits variable" 159 | } 160 | } 161 | ``` 162 | -------------------------------------------------------------------------------- /src/file_formats/vl32.md: -------------------------------------------------------------------------------- 1 | # 32-Bit Voxel List (VL32) 2 | 3 | VL32 is a simple, binary, intermediate file format used in the code of this research project. 4 | 5 | **Extension:** `.vl32`
6 | **Media Type:** `model/x-vl32` 7 | 8 | ## Specification 9 | 10 | VL32 can be specified in only a few lines of StructLang: 11 | 12 | ```rust 13 | def u8 = unsigned 8_bit integer 14 | def i32 = big_endian twos_complement 32_bit integer 15 | 16 | struct main { 17 | voxel[] voxels 18 | } 19 | 20 | struct voxel { 21 | i32 x 22 | i32 y 23 | i32 z 24 | argb32 color 25 | } 26 | 27 | struct argb32 { 28 | u8 alpha 29 | u8 red 30 | u8 green 31 | u8 blue 32 | } 33 | ``` 34 | 35 | Voxels with a color that has an `alpha` of zero are treated as void. 36 | 37 | ## Use Case 38 | 39 | VL32 is largely used for benchmarking compression efficiency. 40 | Any compression effort should yield significantly higher entropy than this format. 41 | 42 | One of the significant advantages is that there doesn't need to be any header information. 43 | When reading, voxels are simply loaded until the EOF is reached. 44 | Also there is no difference in data size between the file encoded on disk and its typical in-memory representation, 45 | such as a `std::vector` of voxels. 46 | -------------------------------------------------------------------------------- /src/file_formats/vlascii.md: -------------------------------------------------------------------------------- 1 | # ASCII Voxel List (VLASCII) 2 | 3 | VLASCII is a simple, text-based, intermediate file format used in the code of this research project. 4 | 5 | **Extension:** `.vlascii`
6 | **Media Type:** `model/x-vlascii` 7 | 8 | ## Specification 9 | 10 | Here the specification, in [EBNF](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form). 11 | 12 | ```ebnf 13 | vlascii = { line }; 14 | (* lines can be empty *) 15 | line = [comment | voxel], {" "}, nl; (* trailing space allowed *) 16 | 17 | comment = "#", { ?any character? } - nl; 18 | voxel = xyz, space, color, space; 19 | xyz = integer, space, integer, space, integer; 20 | color = (h, h, h, h, h, h) | (h, h, h); 21 | 22 | h = ?hexadecimal digit?; 23 | integer = ["-"], ?decimal digit?, { ?decimal digit? }; 24 | nl = ?newline character?; 25 | space = " ", { " " }; 26 | ``` 27 | 28 | ## Example 29 | 30 | ```sh 31 | # red voxel at 0, 0, 0 32 | 0 0 0 ff0000 33 | # white voxel at 0, 1, 0 34 | 0 1 0 fff 35 | # black voxel at 0, 0, 1 36 | 0 0 1 000 37 | ``` 38 | -------------------------------------------------------------------------------- /src/flvc/flvc.md: -------------------------------------------------------------------------------- 1 | # Free Lossless Voxel Compression (FLVC) 2 | 3 | FLVC is the file format produced based on the results of the presented research. 4 | 5 | **Extension:** `.flvc`
6 | **Media Type:** `model/x-flvc`
7 | **Magic Bytes:** `"\xff\x11\x33\xccflvc"` = `ff 11 33 cc 66 6c 76 63` 8 | 9 | ## Container Format Specification 10 | 11 | ```rust 12 | // TYPE DEFINITIONS ============================================================ 13 | 14 | type u8 = unsigned integer<8> 15 | type u16 = little_endian unsigned integer<16> 16 | type u32 = little_endian unsigned integer<32> 17 | type u64 = little_endian unsigned integer<64> 18 | 19 | type i8 = twos_complement integer<8> 20 | type i16 = little_endian twos_complement integer<16> 21 | type i32 = little_endian twos_complement integer<32> 22 | type i64 = little_endian twos_complement integer<64> 23 | 24 | // CONSTANTS =================================================================== 25 | 26 | enum attribute_modifier : u16 { 27 | // this attribute has no spatial locality 28 | // should be used for random unique ids etc. 29 | NON_LOCAL = 1 30 | // only applicable to the "color" attribute 31 | // whatever color model is used, alpha will be appended to it last 32 | // ARGB is the default, in which alpha is first 33 | ALPHA_LAST = 2 34 | } 35 | 36 | enum attribute_type : u8 { 37 | // 8-bit unsigned integer were any nonzero value is interpreted as true 38 | BOOL = 0x01 39 | 40 | INT_8 = 0x11 // see i8 type 41 | INT_16 = 0x12 // see i16 type 42 | INT_32 = 0x14 // see i32 type 43 | INT_64 = 0x18 // see i64 type 44 | 45 | UINT_8 = 0x21 // see u8 type 46 | UINT_16 = 0x22 // see u16 type 47 | UINT_32 = 0x24 // see u32 type 48 | UINT_64 = 0x28 // see u64 type 49 | 50 | FLOAT_32 = 0x41 // 32-bit floating point 51 | FLOAT_64 = 0x42 // 64-bit floating point 52 | } 53 | 54 | enum builtin_identifiers : string8 { 55 | // attributes will be used as the color of the voxel 56 | COLOR = "color" 57 | // attributes will be used as the normal of the voxel 58 | NORMAL = "normal" 59 | } 60 | 61 | // HELPER STRUCTS ============================================================== 62 | 63 | struct string8 { 64 | nonzero u8 size 65 | // ASCII-encoded 66 | max<127> u8[size] content 67 | } 68 | 69 | // HEADER ====================================================================== 70 | 71 | struct main { 72 | // 8 bytes of file magic 73 | u64 magic = 0xff11_33cc_666c_7663 74 | 75 | // major version and minor version, currently 0.1 76 | u8 version_major = 0 77 | u8 version_minor = 1 78 | 79 | // The offset of the volume from the origin 80 | i32[3] volume_offset 81 | // The exact dimensions of the voxel volume. 82 | // The SVO has to contain these dimensions, but may be larger internally. 83 | // (SVOs can only have power-of-two dimensions) 84 | u32[3] volume_size 85 | 86 | // 1 if the volume contains no voxels, else 0 87 | u8 empty 88 | 89 | // pads the fixed-size header content to a total length of 40 bytes 90 | u8[5] padding = "(def)" 91 | 92 | u16 definitions_size 93 | attribute_definition[definitions_size] definitions 94 | 95 | // A visual separator between header and content, visible when opening files 96 | // in a hex editor. 97 | // Also useful to detect reading past the header in implementations. 98 | u8 reserved = '|' 99 | 100 | // Only store a zlib-encoded stream for non-empty SVOs. 101 | // Emptyness is indicated by the "empty" variable above. 102 | if (!header.empty) { 103 | // (extern because can't be fully defined in StructLang) 104 | extern zlib_stream content 105 | } 106 | } 107 | 108 | struct attribute_definition { 109 | // unique identifier of the attribute 110 | // certain values such as "color" are builtin and reserved 111 | // (see enum builtin_identifiers) 112 | string8 identifier 113 | 114 | // type of the attribute 115 | attribute_type atype 116 | 117 | // If zero, the type is a variable sized-array. 118 | // If not zero, this indicates that the type is a fixed-size array-type or 119 | // vector-type. 120 | // The position attribute must have a cardinality of 3! 121 | u8 cardinality 122 | 123 | // bitmap storing all modifiers 124 | u16 modifiers 125 | } 126 | ``` 127 | `header.size` is not strictly necessary for decoding, but it can be helpful when converting directly to a 3D array 128 | or other format which requires a size upon construction. 129 | 130 | The attribute definitions allow us to practically store any data we want inside the format. 131 | For example, store an RGB24 value: 132 | 133 | ```rust 134 | modifiers = 0 135 | atype = UINT_8 136 | cardinality = 3 137 | identifier = "color" 138 | ``` 139 | 140 | The actual `content` is too complex to be expressed in StructLang. 141 | -------------------------------------------------------------------------------- /src/flvc/results.md: -------------------------------------------------------------------------------- 1 | # FLVC Performance, Conclusions 2 | 3 | 22 | 23 | ## Examples 24 | 25 | In the following section, we will look at three concrete examples of real world 26 | performance of the FLVC codec. 27 | 28 | !!! note 29 | All test were performed on the ramdisk of a Debian 11 Desktop.
30 | **Processor:** Ryzen 9 3900X
31 | **Memory:** 64 GiB 3200MHz 32 | 33 | ### Spacestation 34 | 35 | Spacestation 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
Voxels 923,566 V
Raw Size 14,777,056 B
Encoded Size (FLVC-6)(3.34%) 500,812 B
Encoded Size (FLVC-9)(3.33%) 493,409 B
Encoding Duration (FLVC-6) 1679 ms
Encoding Duration (FLVC-9) 2130 ms
45 | 46 | ### Scrapyard 47 | 48 | Scrapyard 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
Voxels 24,423,655 V
Raw Size (VL32) 390,778,480 B
Compressed Size (FLVC-6)(1.71%) 6,682,496 B
Compressed Size (FLVC-9)(1.69%) 6,602,502 B
Encoding Duration (FLVC-6) 38 s
Encoding Duration (FLVC-9) 44 s
58 | 59 | ### Mars Heightmap 60 | Mars Map 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
Voxels 101,244,604 V
Raw Size 1,619,913,664 B
Encoded Size (FLVC-6)(0.90%) 14,616,607 B
Encoded Size (FLVC-9)(0.86%) 13,914,269 B
Encoding Duration (FLVC-6) 149 s
Encoding Duration (FLVC-9) 163 s
70 | 71 | 72 | ## Conclusions 73 | 74 | ##### Compression Ratio 75 | 76 | Free Lossless Voxel Compression delivers impressive results. 77 | Even for the smaller and somewhat less redundant models, we need less than one 78 | byte per voxel despite starting with 16 bytes per voxel (`x, y, z, argb`). 79 | At best, the file size is reduced by over 99%. 80 | It must be emphasized that in related work, the reference point is typically a 81 | voxel array where only a minuscule fraction consists of voxels. 82 | Here, the reference point is a list of voxels with no empty space between. 83 | 84 | The level of compression has little impact on the size of the produced filed. 85 | At best, a 10% reduction ca be seen, at worst, almost none. 86 | 87 | ##### Time 88 | 89 | Execution time can be perceived as excessive for very large models. 90 | As can be concluded from previous sections, most of this time is spent reading 91 | in VL32 data and constructing the SVO. 92 | For example, of the 149 seconds to encode the heightmap at level 6, 108 were 93 | spent constructing the SVO. 94 | This is a problem that can not be easily resolved algorithmically and is 95 | inherent to manipulating large quantities of data. 96 | Once again, the compression level has comparably little impact: here on the 97 | encoding duration. 98 | 99 | ##### Further Improvements 100 | 101 | Some compression ratio improvements could be achieved by choosing a different 102 | entropy coder. 103 | For example, [Facebook's Zstandard](https://github.com/facebook/zstd) is a more 104 | recent and promising technology than zlib. 105 | A slight improvement in compression speed is also likely. 106 | 107 | However, the biggest bottleneck as of now is the time it takes to construct 108 | the SVO while also reading VL32 data. 109 | A potential solution would be to use multiple threads: One for reading the 110 | VL32 file and one for constructing the SVO. 111 | At most, this would reduce the duration of first part of FLVC encoding by 50%. 112 | 113 | Another potential approach would be to create multiple, independent volumes, 114 | which are all encoded by a separate thread. 115 | Potentially, separate zlib streams could be created as well to avoid a 116 | bottleneck during entropy coding. 117 | However, this would require further modifications of the FLVC standard and is 118 | not possible merely by optimizing the reference implementation. 119 | -------------------------------------------------------------------------------- /src/graphviz/acc_depth_first.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=false 4 | node [shape=circle] 5 | 6 | 1 -> 2 -> "5/3" -> "7/4" 7 | "5/3" -> "8/5" 8 | 2 -> 6 9 | 1 -> "3/7" 10 | 1 -> "4/8" -> 9 11 | } 12 | -------------------------------------------------------------------------------- /src/graphviz/breadth_first.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=false 4 | node [shape=circle] 5 | 6 | 1 -> 2 -> 5 -> 8 7 | 5 -> 9 8 | 2 -> 6 9 | 1 -> 3 10 | 1 -> 4 -> 7 11 | } 12 | -------------------------------------------------------------------------------- /src/graphviz/dag.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape = record] 4 | root [label="1 | 00 | 1 | 000 | 1"] 5 | 6 | b0 [label=" 1 | 00 | 1 | 0000"] 7 | b1 [label="+4"] 8 | b2 [label="000 | 1| 000 | 1"] 9 | 10 | c00 [shape=none, label=<#d13232>] 11 | c01 [shape=none, label=<#6c6e3b>] 12 | c20 [shape=none, label=<#1d6bd1>] 13 | c21 [shape=none, label=<#bd320b>] 14 | 15 | root:f0 -> b0 16 | root:f1 -> b1 17 | root:f2 -> b2 18 | b0:f0 -> c00 19 | b0:f1 -> c01 20 | b2:f0 -> c20 [weight=5] 21 | b2:f1 -> c21 [weight=5] 22 | 23 | b1 -> c20 [style=dashed] 24 | b1 -> c21 [style=dashed] 25 | } 26 | -------------------------------------------------------------------------------- /src/graphviz/depth_first.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=false 4 | node [shape=circle] 5 | 6 | 1 -> 2 -> 3 -> 4 7 | 3 -> 5 8 | 2 -> 6 9 | 1 -> 7 10 | 1 -> 8 -> 9 11 | } 12 | -------------------------------------------------------------------------------- /src/graphviz/octree.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape = record] 4 | root [label="1 | 00 | 1 | 000 | 1"] 5 | 6 | b0 [label=" 1 | 00 | 1 | 0000"] 7 | b1 [label="00000000"] 8 | b2 [label="000 | 1| 0000"] 9 | 10 | c00 [shape=none, label=<#d13232>] 11 | c01 [shape=none, label=<#6c6e3b>] 12 | c20 [shape=none, label=<#1d6bd1>] 13 | 14 | root:f0 -> b0 15 | root:f1 -> b1 16 | root:f2 -> b2 17 | b0:f0 -> c00 18 | b0:f1 -> c01 19 | b2:f0 -> c20 20 | } 21 | -------------------------------------------------------------------------------- /src/graphviz/octree_complete_branches.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | // splines=false 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label=" 1 | 1 | 1 | 1| 1| 1| 1| 1"] 6 | 7 | b0 [label=" 1 | 1 | 1 | 1| 1| 1| 1| 1"] 8 | bx [label="..."] 9 | b7 [label=" 1 | 1 | 1 | 1| 1| 1| 1| 1"] 10 | 11 | c0 [shape=none, label=<#d33>] 12 | c1 [shape=none, label=<#663>] 13 | // c2 [shape=none, label=<#4ca>] 14 | // c3 [shape=none, label=<#14a>] 15 | // c4 [shape=none, label=<#000>] 16 | // c5 [shape=none, label=<#555>] 17 | cx [shape=none, label="..."] 18 | c6 [shape=none, label=<#c00>] 19 | c7 [shape=none, label=<#c05>] 20 | 21 | c70 [shape=none, label=<#16d>] 22 | c7x [shape=none, label="..."] 23 | c77 [shape=none, label=<#c82>] 24 | 25 | root:f0 -> b0 26 | root -> bx [style=bold] 27 | root:f7 -> b7 28 | 29 | b0:f0 -> c0 30 | b0:f1 -> c1 31 | // b0:f2 -> c2 32 | // b0:f3 -> c3 33 | // b0:f4 -> c4 34 | // b0:f5 -> c5 35 | // b0:f2 -> cx 36 | // b0:f3 -> cx 37 | // b0:f4 -> cx 38 | // b0:f5 -> cx 39 | b0 -> cx [style=bold] 40 | b0:f6 -> c6 41 | b0:f7 -> c7 42 | 43 | b7:f0 -> c70 44 | b7 -> c7x [style=bold] 45 | b7:f7 -> c77 46 | } 47 | -------------------------------------------------------------------------------- /src/graphviz/octree_complete_branches_optimization.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | splines=false 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="00000000"] 6 | 7 | c00 [shape=none, label=<#d33>] 8 | c01 [shape=none, label=<#663>] 9 | c0x [shape=none, label="..."] 10 | c06 [shape=none, label=<#c00>] 11 | c07 [shape=none, label=<#c05>] 12 | 13 | cxx [shape=none, label="..."] 14 | 15 | c77 [shape=none, label=<#c82>] 16 | 17 | root -> c00 18 | root -> c01 19 | root -> c0x [style=bold] 20 | root -> c06 21 | root -> cxx 22 | root -> c07 23 | root -> c77 24 | } 25 | -------------------------------------------------------------------------------- /src/graphviz/octree_node_index: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape=box] 4 | 5 | "**" -> "0*" 6 | "**" -> "1*" 7 | "0*" -> 00 8 | "0*" -> 01 9 | "1*" -> 10 10 | "1*" -> 11 11 | } 12 | -------------------------------------------------------------------------------- /src/graphviz/octree_optimization.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | 6 | a [shape=none, margin=0, label=< 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
b
33 | >,fontname="monospace"] 34 | 35 | b [shape=none, margin=0, label=< 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
b
46 | >,fontname="monospace"] 47 | 48 | c [shape=square,label="b",fontname="monospace"] 49 | 50 | a -> b [style=dotted,minlen=2,fontname="monospace"] 51 | b -> c [style=dotted,minlen=2,fontname="monospace"] 52 | } 53 | -------------------------------------------------------------------------------- /src/graphviz/octree_serial.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | splines=spline 4 | rankdir=LR 5 | node [shape = record] 6 | 7 | root [label="{1 | 00 | 1 | 000 | 1}"] 8 | 9 | b0 [label="{ 1 | 00 | 1 | 0000}"] 10 | b1 [label="00000000"] 11 | b2 [label="{000 | 1| 0000}"] 12 | 13 | c00 [shape=none, label=<#d13232>] 14 | c01 [shape=none, label=<#6c6e3b>] 15 | c20 [shape=none, label=<#1d6bd1>] 16 | 17 | root -> b0 -> c00 -> c01 -> b1 -> b2 -> c20 [weight=100, style=invis] 18 | 19 | root:f0:n -> b0:nw 20 | root:f1:s -> b1:s 21 | root:f2:s -> b2:s 22 | b0:f0:n -> c00:n 23 | b0:f1:n -> c01:n 24 | b2:f0:n -> c20:n 25 | } 26 | -------------------------------------------------------------------------------- /src/graphviz/octree_squashed.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | node [shape = record] 4 | root [label=" 1 | 00 | 1 | 00000000...00000000 | 1| 0000"] 5 | 6 | c00 [shape=none, label=<#d13232>] 7 | c01 [shape=none, label=<#6c6e3b>] 8 | c20 [shape=none, label=<#1d6bd1>] 9 | 10 | root:f0 -> c00 11 | root:f1 -> c01 12 | root:f2 -> c20 13 | } 14 | -------------------------------------------------------------------------------- /src/graphviz/render-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for f in *.dot; do 4 | out="../img/graph/${f%.dot}.svg" 5 | dot "$f" -o "$out" -Tsvg 6 | done 7 | -------------------------------------------------------------------------------- /src/graphviz/simple_growth.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | rankdir=LR 4 | 5 | source [shape=record,label="{1|3}|{0|2}",fontname="monospace"] 6 | target [shape=record,label="{|||}|{|||}|{1|3||}|{0|2||}",fontname="monospace"] 7 | 8 | source -> target [minlen=3,style=dotted] 9 | } 10 | -------------------------------------------------------------------------------- /src/graphviz/test_model.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="1 |00 | 1 |00 | 1 | 1"] 6 | 7 | b_red [label=" 1 |0 | 1 | 1 |0 | 1 | 1 | 1"] 8 | b_gra [label=" 1| 1| 1| 1| 1| 1| 1| 1"] 9 | b_wht [label="0 | 1 |000000"] 10 | b_aqu [label=" 1 |000000 | 1"] 11 | 12 | red [shape=rectangle, label=<ffff000a>] 13 | org [shape=rectangle, label=<ffff8b33>] 14 | gra [shape=rectangle, label=<ff646464>] 15 | wht [shape=rectangle, label=<ffffffff>] 16 | grn [shape=rectangle, label=<ff33ff4c>] 17 | blu [shape=rectangle, label=<ff3373ff>] 18 | 19 | root:f0 -> b_red 20 | root:f3 -> b_gra 21 | root:f6 -> b_wht 22 | root:f7 -> b_aqu 23 | 24 | b_red:f0 -> org 25 | b_red:f2 -> red 26 | b_red:f3 -> red 27 | b_red:f5 -> org 28 | b_red:f6 -> red 29 | b_red:f7 -> red 30 | 31 | b_aqu:f0 -> grn 32 | b_aqu:f7 -> blu 33 | 34 | b_wht:f1 -> wht 35 | 36 | b_gra:f0 -> gra 37 | b_gra:f1 -> gra 38 | b_gra:f2 -> gra 39 | b_gra:f3 -> gra 40 | b_gra:f4 -> gra 41 | b_gra:f5 -> gra 42 | b_gra:f6 -> gra 43 | b_gra:f7 -> gra 44 | } 45 | -------------------------------------------------------------------------------- /src/graphviz/test_model_delta.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="1 |00 | 1 |00 | 1 | 1| ff33000a"] 6 | 7 | b_red [label=" 1 |0 | 1 | 1 |0 | 1 | 1 | 1| 00cc0000"] 8 | b_gra [label=" 1| 1| 1| 1| 1| 1| 1| 1| 0031645a"] 9 | b_wht [label="0 | 1 |000000 | 00ccfff5"] 10 | b_aqu [label=" 1 |000000 | 1 | 00007342"] 11 | 12 | red [shape=rectangle, label=<00000000>] 13 | org [shape=rectangle, label=<00008b29>] 14 | gra [shape=rectangle, label=<00000000>] 15 | wht [shape=rectangle, label=<00000000>] 16 | grn [shape=rectangle, label=<00008c00>] 17 | blu [shape=rectangle, label=<000000b3>] 18 | 19 | root:f0 -> b_red 20 | root:f3 -> b_gra 21 | root:f6 -> b_wht 22 | root:f7 -> b_aqu 23 | 24 | b_red:f0 -> org 25 | b_red:f2 -> red 26 | b_red:f3 -> red 27 | b_red:f5 -> org 28 | b_red:f6 -> red 29 | b_red:f7 -> red 30 | 31 | b_aqu:f0 -> grn 32 | b_aqu:f7 -> blu 33 | 34 | b_wht:f1 -> wht 35 | 36 | b_gra:f0 -> gra 37 | b_gra:f1 -> gra 38 | b_gra:f2 -> gra 39 | b_gra:f3 -> gra 40 | b_gra:f4 -> gra 41 | b_gra:f5 -> gra 42 | b_gra:f6 -> gra 43 | b_gra:f7 -> gra 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/graphviz/test_model_min.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | rankdir=LR 3 | bgcolor=transparent 4 | node [shape = record] 5 | root [label="1 |00 | 1 |00 | 1 | 1| ff33000a"] 6 | 7 | b_red [label=" 1 |0 | 1 | 1 |0 | 1 | 1 | 1| ffff000a"] 8 | b_gra [label=" 1| 1| 1| 1| 1| 1| 1| 1| ff646464"] 9 | b_wht [label="0 | 1 |000000 | ffffffff"] 10 | b_aqu [label=" 1 |000000 | 1 | ff33734c"] 11 | 12 | red [shape=rectangle, label=<ffff000a>] 13 | org [shape=rectangle, label=<ffff8b33>] 14 | gra [shape=rectangle, label=<ff646464>] 15 | wht [shape=rectangle, label=<ffffffff>] 16 | grn [shape=rectangle, label=<ff33ff4c>] 17 | blu [shape=rectangle, label=<ff3373ff>] 18 | 19 | root:f0 -> b_red 20 | root:f3 -> b_gra 21 | root:f6 -> b_wht 22 | root:f7 -> b_aqu 23 | 24 | b_red:f0 -> org 25 | b_red:f2 -> red 26 | b_red:f3 -> red 27 | b_red:f5 -> org 28 | b_red:f6 -> red 29 | b_red:f7 -> red 30 | 31 | b_aqu:f0 -> grn 32 | b_aqu:f7 -> blu 33 | 34 | b_wht:f1 -> wht 35 | 36 | b_gra:f0 -> gra 37 | b_gra:f1 -> gra 38 | b_gra:f2 -> gra 39 | b_gra:f3 -> gra 40 | b_gra:f4 -> gra 41 | b_gra:f5 -> gra 42 | b_gra:f6 -> gra 43 | b_gra:f7 -> gra 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/graphviz/unilateral_growth.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | bgcolor=transparent 3 | rankdir=LR 4 | 5 | source [shape=record,label="{1|3}|{0|2}",fontname="monospace"] 6 | target [shape=record,label="{|||}|{|1|3|}|{|0|2|}|{|||}",fontname="monospace"] 7 | 8 | source -> target [minlen=3,style=dotted] 9 | } 10 | -------------------------------------------------------------------------------- /src/img/cube.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/img/graph/README.txt: -------------------------------------------------------------------------------- 1 | The files in this directory are auto-generated. 2 | Do not put user files in here! 3 | -------------------------------------------------------------------------------- /src/img/graph/acc_depth_first.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 3/7 32 | 33 | 3/7 34 | 35 | 36 | 37 | 1->3/7 38 | 39 | 40 | 41 | 42 | 43 | 4/8 44 | 45 | 4/8 46 | 47 | 48 | 49 | 1->4/8 50 | 51 | 52 | 53 | 54 | 55 | 5/3 56 | 57 | 5/3 58 | 59 | 60 | 61 | 2->5/3 62 | 63 | 64 | 65 | 66 | 67 | 6 68 | 69 | 6 70 | 71 | 72 | 73 | 2->6 74 | 75 | 76 | 77 | 78 | 79 | 7/4 80 | 81 | 7/4 82 | 83 | 84 | 85 | 5/3->7/4 86 | 87 | 88 | 89 | 90 | 91 | 8/5 92 | 93 | 8/5 94 | 95 | 96 | 97 | 5/3->8/5 98 | 99 | 100 | 101 | 102 | 103 | 9 104 | 105 | 9 106 | 107 | 108 | 109 | 4/8->9 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/img/graph/breadth_first.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 3 32 | 33 | 3 34 | 35 | 36 | 37 | 1->3 38 | 39 | 40 | 41 | 42 | 43 | 4 44 | 45 | 4 46 | 47 | 48 | 49 | 1->4 50 | 51 | 52 | 53 | 54 | 55 | 5 56 | 57 | 5 58 | 59 | 60 | 61 | 2->5 62 | 63 | 64 | 65 | 66 | 67 | 6 68 | 69 | 6 70 | 71 | 72 | 73 | 2->6 74 | 75 | 76 | 77 | 78 | 79 | 8 80 | 81 | 8 82 | 83 | 84 | 85 | 5->8 86 | 87 | 88 | 89 | 90 | 91 | 9 92 | 93 | 9 94 | 95 | 96 | 97 | 5->9 98 | 99 | 100 | 101 | 102 | 103 | 7 104 | 105 | 7 106 | 107 | 108 | 109 | 4->7 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/img/graph/depth_first.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 7 32 | 33 | 7 34 | 35 | 36 | 37 | 1->7 38 | 39 | 40 | 41 | 42 | 43 | 8 44 | 45 | 8 46 | 47 | 48 | 49 | 1->8 50 | 51 | 52 | 53 | 54 | 55 | 3 56 | 57 | 3 58 | 59 | 60 | 61 | 2->3 62 | 63 | 64 | 65 | 66 | 67 | 6 68 | 69 | 6 70 | 71 | 72 | 73 | 2->6 74 | 75 | 76 | 77 | 78 | 79 | 4 80 | 81 | 4 82 | 83 | 84 | 85 | 3->4 86 | 87 | 88 | 89 | 90 | 91 | 5 92 | 93 | 5 94 | 95 | 96 | 97 | 3->5 98 | 99 | 100 | 101 | 102 | 103 | 9 104 | 105 | 9 106 | 107 | 108 | 109 | 8->9 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/img/graph/huffman-start.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 14 | a 15 | 16 | a 17 | 18 | 19 | 20 | b 21 | 22 | b 23 | 24 | 25 | 26 | c 27 | 28 | c 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/img/graph/octree_complete_branches_optimization.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | root 14 | 15 | 00000000 16 | 17 | 18 | 19 | c00 20 | #d33 21 | 22 | 23 | 24 | root->c00 25 | 26 | 27 | 28 | 29 | 30 | c01 31 | #663 32 | 33 | 34 | 35 | root->c01 36 | 37 | 38 | 39 | 40 | 41 | c0x 42 | ... 43 | 44 | 45 | 46 | root->c0x 47 | 48 | 49 | 50 | 51 | 52 | c06 53 | #c00 54 | 55 | 56 | 57 | root->c06 58 | 59 | 60 | 61 | 62 | 63 | c07 64 | #c05 65 | 66 | 67 | 68 | root->c07 69 | 70 | 71 | 72 | 73 | 74 | cxx 75 | ... 76 | 77 | 78 | 79 | root->cxx 80 | 81 | 82 | 83 | 84 | 85 | c77 86 | #c82 87 | 88 | 89 | 90 | root->c77 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/img/graph/octree_growth.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | 14 | source 15 | 16 | 1 17 | 18 | 3 19 | 20 | 0 21 | 22 | 2 23 | 24 | 25 | 26 | target 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 1 39 | 40 | 3 41 | 42 | 43 | 44 | 45 | 46 | 0 47 | 48 | 2 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | source->target 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/img/graph/octree_node_index.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | ** 14 | 15 | ** 16 | 17 | 18 | 19 | 0* 20 | 21 | 0* 22 | 23 | 24 | 25 | **->0* 26 | 27 | 28 | 29 | 30 | 31 | 1* 32 | 33 | 1* 34 | 35 | 36 | 37 | **->1* 38 | 39 | 40 | 41 | 42 | 43 | 00 44 | 45 | 00 46 | 47 | 48 | 49 | 0*->00 50 | 51 | 52 | 53 | 54 | 55 | 01 56 | 57 | 01 58 | 59 | 60 | 61 | 0*->01 62 | 63 | 64 | 65 | 66 | 67 | 10 68 | 69 | 10 70 | 71 | 72 | 73 | 1*->10 74 | 75 | 76 | 77 | 78 | 79 | 11 80 | 81 | 11 82 | 83 | 84 | 85 | 1*->11 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/img/graph/octree_squashed.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | root 14 | 15 | 1 16 | 17 | 00 18 | 19 | 1 20 | 21 | 00000000...00000000 22 | 23 | 1 24 | 25 | 0000 26 | 27 | 28 | 29 | c00 30 | #d13232 31 | 32 | 33 | 34 | root:f0->c00 35 | 36 | 37 | 38 | 39 | 40 | c01 41 | #6c6e3b 42 | 43 | 44 | 45 | root:f1->c01 46 | 47 | 48 | 49 | 50 | 51 | c20 52 | #1d6bd1 53 | 54 | 55 | 56 | root:f2->c20 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/img/graph/simple_growth.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | source 14 | 15 | 1 16 | 17 | 3 18 | 19 | 0 20 | 21 | 2 22 | 23 | 24 | 25 | target 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 1 44 | 45 | 3 46 | 47 | 48 | 49 | 50 | 51 | 0 52 | 53 | 2 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | source->target 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/img/graph/unilateral_growth.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | g 11 | 12 | 13 | source 14 | 15 | 1 16 | 17 | 3 18 | 19 | 0 20 | 21 | 2 22 | 23 | 24 | 25 | target 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 1 38 | 39 | 3 40 | 41 | 42 | 43 | 44 | 45 | 0 46 | 47 | 2 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | source->target 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/img/hilbert.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/img/hilbert3d.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/hilbert3d.gif -------------------------------------------------------------------------------- /src/img/model/chessmaster3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/chessmaster3.png -------------------------------------------------------------------------------- /src/img/model/hilbert0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/hilbert0.png -------------------------------------------------------------------------------- /src/img/model/hilbert1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/hilbert1.png -------------------------------------------------------------------------------- /src/img/model/mars_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/mars_map.png -------------------------------------------------------------------------------- /src/img/model/ragged_cluster_magica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/ragged_cluster_magica.png -------------------------------------------------------------------------------- /src/img/model/scrapyard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/scrapyard.png -------------------------------------------------------------------------------- /src/img/model/spacestation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/spacestation.png -------------------------------------------------------------------------------- /src/img/model/test_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/model/test_model.png -------------------------------------------------------------------------------- /src/img/nested_iter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/img/perlin_noise_mve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/perlin_noise_mve.png -------------------------------------------------------------------------------- /src/img/pipeline.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | I love SVG! 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/img/render-svg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$#" -lt 2 ]]; then 4 | printf "Usage: render-svg [height]\n" 5 | exit 1 6 | fi 7 | 8 | file_in="$1" 9 | file_out="$(basename "$file_in" .svg).png" 10 | 11 | width="$2" 12 | 13 | if [[ "$#" -ge 3 ]]; then 14 | height="$3" 15 | rsvg-convert -w "$width" -h "$height" "$file_in" > "$file_out" 16 | else 17 | rsvg-convert -w "$width" "$file_in" > "$file_out" 18 | fi 19 | 20 | -------------------------------------------------------------------------------- /src/img/voxel_noise_mve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/voxel_noise_mve.png -------------------------------------------------------------------------------- /src/img/z_order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eisenwave/voxel-compression-docs/8817b0b47d53c4a3316204544d967443e55605c1/src/img/z_order.png -------------------------------------------------------------------------------- /src/img/z_order.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 51 | 52 | 54 | 55 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | # Compression of Voxel Models 2 | 3 | ## Abstract 4 | 5 | This website contains the documentation of my research project at TU Dresden. 6 | The goal of the project is to develop an efficient algorithm for compressing voxel models. 7 | As an input format, an unsorted list of 3D integer coordinates and attribute data is used. 8 | Multiple methods for encoding geometry data including 9 | Cuboid Extraction (CE), 10 | Sparse Voxel Octrees (SVOs) with Space-Filling Curves, and 11 | Run-Length Encoding (RLE) 12 | are explained and then compared in terms of complexity, compression ratio, and real life performance. 13 | CE fails based on its high complexity, SVOs and RLE perform almost identically in terms of compression ratio and 14 | complexity. 15 | SVOs are the clear winner because of their lower real life memory requirements when reading the input data, resulting 16 | in better performance. 17 | 18 | The Free Lossless Voxel Compression (FLVC) codec is developed based on these findings. 19 | Its advantages include arbitrary attribute information per voxel, high performance, streamability, and very low memory 20 | requirements for decoding. 21 | The codec is made available through a FOSS command-line utility which can convert between various common voxel model 22 | formats and the new FLVC format. 23 | 24 | 25 | ##### Relevant Links 26 | 27 | - [FLVC Command-Line Interface](https://github.com/Eisenwave/flvc) 28 | - [This documentation on GitHub](https://eisenwave.github.io/voxel-compression-docs/) 29 | 30 | ##### Notes 31 | 32 | This documentation was written using [MkDocs](https://www.mkdocs.org/). 33 | ^^` 34 | !!! warning 35 | Many functions such as searching or syntax highlighting won't work when opening this project with a `file://` 36 | scheme. 37 | You can browse this site offline by hosting it as a static web page on a local server. 38 | 39 | To name an example, use `python3 -m http.server 8000` in the root directory to host this page locally on port 8000. 40 | Then connect to 41 | -------------------------------------------------------------------------------- /src/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Volumetric Pixels or voxels are an increasingly popular method of representing 3-dimensional data. 4 | Their uses are plentiful such as representing quantized point cloud data, medical scans, acceleration data structures 5 | for VFX, high resolution sculptures, or 3D models with an intentional voxel art style. 6 | Accessing voxels randomly can even be achieved with constant time complexity, all while using relatively simple data 7 | structures. 8 | 9 | However, perhaps because of this simplicity, efficient permanent storage of voxel models is rarely a concern. 10 | Out of more than 20 common voxel file formats, only one 11 | ([Qubicle Binary Tree](related/voxel_formats.md#qubicle-binary-tree)) makes a serious attempt at compression 12 | of voxel models by using [zlib](https://zlib.net/). 13 | Some solutions combining general-purpose technologies such as storing a stack of PNG layers can also be found in formats 14 | like [SVX](related/voxel_formats.md#simple-voxels). 15 | The sophistication of widely used voxel software is overall at a pre-1996 level compared to image compression. 16 | This fact promises enormous improvements in compression ratio for a new file format that was designed specifically 17 | for the purpose of efficiently storing voxel models on disk. 18 | 19 | The goal of this project was to develop an efficient codec for the purpose of on-disk storage of voxel models. 20 | Compression ratio and performance are equally important. 21 | In addition to the overwhelmingly popular approach of using sparse voxel octrees (SVOs) for compact storage, we also 22 | examine alternative solutions such as a variety of run-length encoding schemes (RLE) using different space-filling 23 | curves, including Nested Iteration, Morton Curves, and Hilbert Curves. 24 | 25 | In the following chapters we first examine geometry-only encoding of voxel models. 26 | RLE and SVO techniques are examined thoroughly and compared against each other in compression and performance. 27 | The reference point for compression efficiency is a list of points with quantized coordinates. 28 | This was the size of the input data is directly proportional to the number of voxels. 29 | Based on the findings, we discuss a suitable attribute encoding scheme that can be well combined with our geometry 30 | encoding scheme of choice. 31 | Finally, the FLVC codec which incorporates all our findings is presented. 32 | 33 | ## Related Work 34 | 35 | [Schnabel et al.](related/literature.md#octree-based-point-cloud-compression) first presented in 2006 how sparse voxel 36 | octrees can be used to efficiently store point-cloud data. 37 | A technique is suggested where a single byte is used to encode the existence of a child node, which represents 38 | individual voxels at the bottommost level of the SVO. 39 | While this technique was not its main subject, the suggested approach can be further optimized by encoding recursively 40 | occupied nodes of the octree specially. 41 | The research also shows that the number of child nodes is not uniformly distributed and may show significant 42 | redundancy based on the model, which can be exploited by an arithmetic coder. 43 | 44 | [Byrne et al.](related/literature.md#vola) designed an efficient file format named VOLA for storing quantized point 45 | cloud data with no attributes other than geometry. 46 | VOLA stores voxels not as an array -as is often done at runtime- but as an octree where to layers are 47 | combined into one, creating a tree with a branching factor of 64. 48 | The performance of this approach is outdone by our codec, but VOLA was an inspiration. 49 | 50 | Most other contemporary research is focused on the use of voxels at runtime. 51 | In part, this is because voxels are being used primarily as VFX accelerators where polygonal models are unsuited to 52 | achieve certain effects in real time, such as global illumination. 53 | This task inherently comes with strict performance requirements. 54 | 55 | [Laine et al.](related/literature.md#efficient-svos) presents a sparse voxel octree-based technique for representing 56 | geometry and shading attributes. 57 | Some techniques found in our implementation are similar to the presented memory layout. 58 | Namely, the use of an 8-bit child mask to encode which children of a parent node exist was inspired by this paper. 59 | 60 | [Kämpe et al.](related/literature.md#high-resolution-sparse-voxel-dags) show that SVOs can be further compactified 61 | by merging identical trees and generalizing to sparse voxel directed acyclic graphs (SVDAGs). 62 | This approach was developed for realtime rendering with 32-bit pointers encoding links between nodes. 63 | While a significant reduction in space can be observed, this technique does not provide significant benefits to a 64 | pointerless structure with 8-bit child masks, which is why it was not used in our project. 65 | -------------------------------------------------------------------------------- /src/js/extra.js: -------------------------------------------------------------------------------- 1 | // disable language-auto-detection 2 | // necessary to prevent no-code markdown preformatted blocks from being highlighted 3 | hljs.configure({languages: []}); 4 | hljs.initHighlightingOnLoad(); 5 | -------------------------------------------------------------------------------- /src/js/mathjax_config.js: -------------------------------------------------------------------------------- 1 | MathJax.Hub.Config({ 2 | config: ["MMLorHTML.js"], 3 | jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"], 4 | extensions: [], 5 | showMathMenu: true 6 | }); 7 | -------------------------------------------------------------------------------- /src/properties.md: -------------------------------------------------------------------------------- 1 | # Properties of Voxel Models 2 | 3 | The cornerstone of compression is discovering and eliminating redundancies in data. 4 | We must first recognize these redundancies by observing the nature of voxel models. 5 | There are plenty of properties which we can exploit, as described in the following sections. 6 | 7 | ## Geometric/Spatial Locality 8 | 9 | ![Voxel Noise](img/perlin_noise_mve.png)
10 | *Normalized 3D Perlin Noise with a threshold of 0.4* 11 | 12 | Voxels rarely come alone. 13 | All 3D models will typically take some distinguished shape. 14 | There will be large areas with filled geometry (voxels) and large empty areas, *air*, or *void*. 15 | In artistic circles these are often described as [negative space](https://en.wikipedia.org/wiki/Negative_space). 16 | 17 | ![Voxel Noise](img/voxel_noise_mve.png)
18 | *Uniform voxel noise with a probability of 0.1 that a voxel is set* 19 | 20 | The only kind of model which has no spatial locality whatsoever would be uniformly distributed noise. (see above) 21 | These kinds of models are the absolute exception and are rarely if ever seen. 22 | 23 | ### Conclusion 24 | 25 | Compression schemes have to be able to describe large volumes of positive and negative space efficiently. 26 | 27 | ## Color/Attribute Locality 28 | 29 | ![Ragged Cluster ](img/model/ragged_cluster_magica.png) 30 | *"Ragged Cluster" model visualized in Magica Voxel* 31 | 32 | Color and other attributes such as normals correlate with geometry. 33 | This means that the color distance between neighboring voxels is significantly lower than the distance of random points 34 | in RGB space. 35 | 36 | In fact, this correlation is dramatically high. 37 | For the above model, the average euclidean distance of any unique pair of neighboring voxel colors 38 | $(0, 0, 0) \le (r, g, b) \le (255, 255, 255)$ 39 | is $8.56$. 40 | Normalized for positions in a unit cube instead this is $0.03357$. 41 | 42 | For uniform random colors, this distance would be equal to 43 | [Robbin's Constant](https://mathworld.wolfram.com/RobbinsConstant.html) which is roughly equal to $0.66170$, almost 44 | 20 times higher. 45 | 46 | ### Conclusion 47 | 48 | Compression schemes should make use of geometric encoding and attach attributes on top of that. 49 | Alternatively voxel compression schemes should encode attributes in a fashion very similar to geometry. 50 | 51 | ## Color Sparsity 52 | 53 | While in principle, plenty of software supports 24-bit True Color RGB or even wider standards, only a small amount of 54 | colors are actually used. 55 | Especially in the field of *Voxel Art*, the 3D-equivalent to [Pixel Art](https://en.wikipedia.org/wiki/Pixel_art), 56 | small palettes are used. 57 | To name an example, [Magica Voxel](https://ephtracy.github.io/) supports 255 unique colors but each individual color 58 | is a 24-bit True Color. 59 | 60 | ### Conclusion 61 | 62 | Compression schemes should be aware of potentially very low color counts and exploit these by building a palette. 63 | A palette will not always be beneficial since in principle, any amount of colors should be present. 64 | However, in many cases this will be beneficial. 65 | -------------------------------------------------------------------------------- /src/statistical_tests.md: -------------------------------------------------------------------------------- 1 | # Statistical Tests to Determine Voxel Model Properties 2 | 3 | The following list should give an overview over possible properties which voxel models are suspected to have. 4 | A description of an algorithm and/or pseudocude is used to provide a potential test. 5 | 6 | 7 | ## Spatial Locality of Different Methods of Iteration Over Voxel Models 8 | 9 | There are various different ways of iterating over a voxel model. 10 | We will consider only two or three, which are relevant to us. 11 | 12 | #### Nested Loop Iteration 13 | This is the traditional method of iterating over multi-dimensional arrays. 14 | ```c 15 | char data[SIZE_X][SIZE_Y][SIZE_Z]; 16 | for (size_t x = 0; x < SIZE_X; ++x) 17 | for (size_t y = 0; y < SIZE_Y; ++y) 18 | for (size_t z = 0; z < SIZE_Z; ++z) 19 | data[x][y][z]; 20 | ``` 21 | It is extremely efficient for traversing memory because it seemlessly iterates over memory locations, as long as the 22 | axes of iteration are in the right order. 23 | The distances between two positions are at best `1` and at worst `SIZE_X + SIZEY`. 24 | However, the spatial locality is much worse when looking at more than one position. 25 | For say, 10 positions the distance between the first and last will be 10, which is comparably far. 26 | 27 | #### Z-Order Iteration 28 | Z-Order iteration traverses space with much higher locality. 29 | It works by traversing all nodes of an octree depth-first. 30 | 3D-Vectors can be converted into "octree positions" by interleaving the bits of the coordinates into a single number. 31 | ```c 32 | char data[SIZE_X][SIZE_Y][SIZE_Z]; 33 | for (size_t x = 0; x < SIZE_X; ++x) 34 | for (size_t y = 0; y < SIZE_Y; ++y) 35 | for (size_t z = 0; z < SIZE_Z; ++z) 36 | data[interleave_bits(x, y, z)]; 37 | ) 38 | ``` 39 | 40 | #### Hilbert-Curve Iteration 41 | Hilbert-Curves have even higher locality than Z-Order iterations, but are considerably better in locality. 42 | See https://slideplayer.com/slide/3370293/ for construction. 43 | In short, space is filled in the following order, which is a Gray Code. 44 | ```json 45 | [[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1], [1, 0, 0]] 46 | ``` 47 | The entry direction for one of these pieces is +Z and the exit-direction is -Y. 48 | This pattern is repeated recursively, but the smaller building blocks have to be mirrored and rotated to fit together 49 | seemlessly into a larger block. 50 | The tremendously useful property here is that the distance between two points in the iteration is at most `1`. 51 | 52 | ### Testing Spatial Locality 53 | Spatial locality can simply be tested by comparing the average distance between each pair of points, triple of points, 54 | etc. within an iteration. 55 | When more than two points are tested, the distances of each unique pair of points can be summed up or averaged. 56 | Hilber-Curve Iteration is expected to deliver the best results on most, if not all scales. 57 | 58 | 59 | ## Correlation of Color and Geometry Deltas 60 | 61 | It is expected that color correlates with positions. 62 | This means that positions which are close to each other should also have similar colors. 63 | To verify this property, each unique pair of points can be iterated over. 64 | The euclidean distance in geometry-space (scaled down to a unit-cube) as well as the euclidean distance in the RGB 65 | color space should be plotted. 66 | The correlation can then be calculated from all data entries. 67 | ```cpp 68 | struct Entry { 69 | double geoDistance; 70 | double colDistance; 71 | }; 72 | struct ColoredPoint { 73 | vec3 geo; 74 | vec3 col; 75 | } 76 | std::vector entries; 77 | for (const std::pair &pair : allPoints) { 78 | double geoDistance = pair.first.geo.distanceTo(pair.second.geo); 79 | double colDistance = pair.first.col.distanceTo(pair.second.col); 80 | entries.emplace_back(geoDistance, colDistance); 81 | } 82 | ``` 83 | -------------------------------------------------------------------------------- /src/svo/optimization.md: -------------------------------------------------------------------------------- 1 | # SVO Optimization 2 | 3 | Sparse Voxel Octrees are often sufficiently compact data structures for computer graphics applications. 4 | However, they still contain a large amount of redundancy and have plenty of potential for optimization. 5 | 6 | We can differentiate between two types of optimizations:
7 | **top-down optimizations** optimize nodes starting from the root node and continue downwards. 8 | **bottom-up optimizations** optimize nodes starting from the leafs and continue upwards. 9 | 10 | *Top-down optimizations* alter the geometric boundaries of the octree but have little effect on the amount of nodes. 11 | This is due to the fact that in any tree, there are more nodes towards the bottom. 12 | Their primary purpose is accelerating access to the deeper layers. 13 | 14 | *Bottom-up optimizations* have no impact on the boundaries of the octree as this solely depends on the maximum depth. 15 | Their primary purpose is decreasing the amount of nodes or reducing nodes in size. 16 | 17 | 18 | ## Single-Octant Optimization 19 | 20 | ![Octree Optimization](../img/graph/octree_optimization.svg)
21 | *Figure 1: Octree Optimization, where b is a sub-branch (visualized using a Quadtree)* 22 | 23 | Once an octree has been fully constructed, unused octants can be optimized or "cut away" recursively. 24 | This can be especially helpful for octrees where all voxels reside very far from the origin. 25 | For instance, we could be encoding voxels with coordinates ranging from 100,000 to 100,050. 26 | Many almost completely empty octree layers would need to be traversed to get to where such locations are stored. 27 | Trimming away such single-octant layers accelerates encoding and decoding. 28 | 29 | This is our first and only *top-down optimization*. 30 | 31 | ### Algorithm 32 | 33 | 1. $s \gets (0,0,0)$ 34 | 2. If the root node $r$ has exactly one branch $b$: 35 | - $s \gets s + 2^{d-2}$ 36 | - $r \gets b$ 37 | - repeat 2. 38 | 39 | $2^d$ is the negated minimum point of our current octree, as described in 40 | [Position Normalization](#position-normalization). 41 | 42 | After this process has been completed, we simply store $s$ alongside the octree. 43 | When decoding, $s$ is added back onto all found positions. 44 | 45 | 46 | ## Complete Branch Optimization 47 | 48 | ![Complete Branch Optimization](../img/graph/octree_complete_branches.svg)
49 | *Figure 2: A Complete (Sub-)Tree* 50 | 51 | Observe the *Figure 2* above. 52 | All nodes are completely filled with `1`, representing that their subtree or color is present. 53 | This demonstrates one of the significant weak points of octrees: 54 | They are very good at trimming away air recursively, but have a very high cost when encoding a completely filled 55 | container. 56 | 57 | In fact, we would be much better off encoding such containers as arrays than using octrees, as octrees only add 58 | redundancy and no benefit in this case. 59 | To optimize such cases, we must eliminate nodes which are recursively filled in, or *complete*. 60 | A voxel model that demonstrates this well is *chessmaster3*: 61 | 62 | ![Chessmaster3](../img/model/chessmaster3.png)
63 | *Figure 3: chessmaster3 Model, visualized in Magica Voxel* 64 | 65 | A very large portion of this model is completely filled in. 66 | In fact, the cuboid base of this model alone is 1088x1088 large and many voxels tall. 67 | When encoding this model, we see the following results: 68 | 69 | | Method | Geometry Bytes | 70 | | ----- | ----- | 71 | SVX | 1031 KiB 72 | Octree | 25044 KiB (~24x) 73 | Tetrahexacontree | 22704 KiB (~22x) 74 | Octree Optimized | 1340 KiB (~1.3x) 75 | Thct. Optimized | 4619 KiB (~4.5x) 76 | 77 | So how could we accomplish a seemingly miraculous drop from 24x worse to nearly identical for octrees? 78 | By simply using the *degenerate case* of a zero-node to encode a complete subtree. 79 | 80 | ![Complete Branch Optimization](../img/graph/octree_complete_branches_optimization.svg)
81 | *Figure 4: The Tree from Figure 2, after optimization.* 82 | 83 | Compare the above figure to *Figure 2*. We are eliminating one layer of nodes and going from the root directly to 84 | the color information. 85 | Of course, the above data only includes geometry bytes, not color bytes. 86 | By eliminating such layers, we can save ourselves 8 nodes on the second level from the bottom, 64 nodes on the third, 87 | and so on. 88 | 89 | Geometrically, it does not even require a lot of space to be completely filled. 90 | We merely need a 4x4x4 volume of voxels to be complete in order to eliminate 8 nodes. 91 | Tetrahexacontrees do not perform nearly as well though. 92 | They require a 16x16x16 volume to be complete and only then is an optimization possible. 93 | The more squashed an octree becomes, the fewer opportunities there are to optimize it. 94 | -------------------------------------------------------------------------------- /src/uncompressed.md: -------------------------------------------------------------------------------- 1 | # Uncompressed Format 2 | 3 | The uncompressed format used for reference in this project is a 32-bit list of voxels. 4 | In this case a voxel is a triple of coordinates and an ARGB integer, meaning that voxels can be partially transparent. 5 | 6 | ## Example Implementation 7 | 8 | Here is a simple example implementation of a 32-bit voxel list in C++. 9 | 10 | ```cpp 11 | struct voxel { 12 | int32_t x; 13 | int32_t y; 14 | int32_t z; 15 | uint8_t a; 16 | uint8_t r; 17 | uint8_t g; 18 | uint8_t b; 19 | } 20 | 21 | std::vector voxel_list; 22 | ``` 23 | 24 | ## Justification - Voxel Arrays vs. Voxel Lists 25 | 26 | There are at least two popular methods of representing voxels in an uncompressed way: 27 | 28 | - 3D-array of colors, aka. voxel array 29 | - array of coordinate/color pairs, aka. voxel list 30 | 31 | The first method is often used in software on a small scale. 32 | Arrays allow for random access in $O(1)$. 33 | They are also used in other research, such as [High Resolution Sparse Voxel DAGs]( 34 | related/literature.md#high-resolution-sparse-voxel-dags). 35 | Despite its popularity, arrays are unsuitable for measuring compression ratios because the entropy of the voxel data 36 | poorly correlates with the size of this representation. 37 | For instance, two voxels at $(1, 1, 1)$ and $(1000, 1000, 1000)$ require 1 gigavoxel of space due to all the empty space 38 | between the two voxels. 39 | However, in the best case where all voxels are present, this method has only constant overhead: that which is necessary 40 | to store the dimensions of the array. 41 | 42 | The second representation -which is the one used here- will require space that linearly scales with the amount of 43 | non-empty voxels. 44 | Note that in the worst case, this could require four times the space of the first method due to the coordinates 45 | being stored explicitly. 46 | This kind of overhead is still preferable to the potential (near) complete waste of space of the first method. 47 | 48 | To summarize, here is a quick overview: 49 | 50 | | | Voxel Array | Voxel List | 51 | | ----- | ----- | ----- | 52 | worst case overhead (space) | $O(\infty)$[^1] | $O(4n)$[^2] 53 | best case overhead (space) | $\Omega(1)$ | $\Omega(4n)$[^2] 54 | random access (time) | $O(1)$ | $O(n)$ 55 | 56 | [^1]: Unbounded because two voxels can be infinitely far apart, creating infinite wasted space / overhead 57 | [^2]: The constant factor of 4 is irrelevant in this notation, but illustrates the extent of the overhead 58 | 59 | ## Serialization 60 | 61 | Serialization of the [VL32](file_formats/vl32.md) representation is trivial because the data structure in memory is 62 | similar, if not identical to its serialized counterpart. 63 | To serialize it, we must simply write each element of the array from first to last to disk. 64 | --------------------------------------------------------------------------------