├── requirements.txt ├── setup.cfg ├── docs ├── requirements.txt ├── build │ ├── html │ │ ├── objects.inv │ │ ├── _static │ │ │ ├── file.png │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── fonts │ │ │ │ ├── Lato-Bold.ttf │ │ │ │ ├── Inconsolata.ttf │ │ │ │ ├── Lato-Regular.ttf │ │ │ │ ├── Lato │ │ │ │ │ ├── lato-bold.eot │ │ │ │ │ ├── lato-bold.ttf │ │ │ │ │ ├── lato-bold.woff │ │ │ │ │ ├── lato-bold.woff2 │ │ │ │ │ ├── lato-italic.eot │ │ │ │ │ ├── lato-italic.ttf │ │ │ │ │ ├── lato-italic.woff │ │ │ │ │ ├── lato-regular.eot │ │ │ │ │ ├── lato-regular.ttf │ │ │ │ │ ├── lato-bolditalic.eot │ │ │ │ │ ├── lato-bolditalic.ttf │ │ │ │ │ ├── lato-italic.woff2 │ │ │ │ │ ├── lato-regular.woff │ │ │ │ │ ├── lato-regular.woff2 │ │ │ │ │ ├── lato-bolditalic.woff │ │ │ │ │ └── lato-bolditalic.woff2 │ │ │ │ ├── RobotoSlab-Bold.ttf │ │ │ │ ├── Inconsolata-Bold.ttf │ │ │ │ ├── Inconsolata-Regular.ttf │ │ │ │ ├── RobotoSlab-Regular.ttf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ └── RobotoSlab │ │ │ │ │ ├── roboto-slab-v7-bold.eot │ │ │ │ │ ├── roboto-slab-v7-bold.ttf │ │ │ │ │ ├── roboto-slab-v7-bold.woff │ │ │ │ │ ├── roboto-slab-v7-bold.woff2 │ │ │ │ │ ├── roboto-slab-v7-regular.eot │ │ │ │ │ ├── roboto-slab-v7-regular.ttf │ │ │ │ │ ├── roboto-slab-v7-regular.woff │ │ │ │ │ └── roboto-slab-v7-regular.woff2 │ │ │ ├── css │ │ │ │ ├── fonts │ │ │ │ │ ├── lato-bold.woff │ │ │ │ │ ├── lato-bold.woff2 │ │ │ │ │ ├── lato-normal.woff │ │ │ │ │ ├── lato-normal.woff2 │ │ │ │ │ ├── Roboto-Slab-Bold.woff │ │ │ │ │ ├── Roboto-Slab-Bold.woff2 │ │ │ │ │ ├── lato-bold-italic.woff │ │ │ │ │ ├── lato-bold-italic.woff2 │ │ │ │ │ ├── Roboto-Slab-Regular.woff │ │ │ │ │ ├── Roboto-Slab-Regular.woff2 │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ │ ├── lato-normal-italic.woff │ │ │ │ │ └── lato-normal-italic.woff2 │ │ │ │ └── badge_only.css │ │ │ ├── documentation_options.js │ │ │ ├── js │ │ │ │ ├── badge_only.js │ │ │ │ ├── html5shiv.min.js │ │ │ │ ├── html5shiv-printshiv.min.js │ │ │ │ ├── theme.js │ │ │ │ └── modernizr.min.js │ │ │ ├── pygments.css │ │ │ ├── doctools.js │ │ │ └── language_data.js │ │ ├── _images │ │ │ └── ex_nerf.png │ │ ├── .buildinfo │ │ ├── _sources │ │ │ ├── ex_nerf.rst.txt │ │ │ ├── svox.rst.txt │ │ │ ├── ex_opt_toy.rst.txt │ │ │ ├── index.rst.txt │ │ │ └── quick.rst.txt │ │ ├── search.html │ │ ├── searchindex.js │ │ ├── ex_nerf.html │ │ └── index.html │ └── doctrees │ │ ├── index.doctree │ │ ├── quick.doctree │ │ ├── svox.doctree │ │ ├── ex_nerf.doctree │ │ ├── environment.pickle │ │ └── ex_opt_toy.doctree ├── source │ ├── images │ │ └── ex_nerf.png │ ├── ex_nerf.rst │ ├── svox.rst │ ├── ex_nerf.py │ ├── ex_opt_toy.py │ ├── ex_opt_toy.rst │ ├── index.rst │ ├── conf.py │ └── quick.rst ├── Makefile └── make.bat ├── .readthedocs.yaml ├── MANIFEST.in ├── setup.py ├── LICENSE.txt ├── README.md └── svox ├── version.py ├── __init__.py ├── csrc ├── CMakeLists.txt ├── include │ ├── data_spec.hpp │ ├── data_spec_packed.cuh │ └── common.cuh ├── svox.cpp ├── quantizer.cpp └── svox_kernel.cu ├── sh.py └── helpers.py /requirements.txt: -------------------------------------------------------------------------------- 1 | torch 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-rtd-theme 3 | sphinxcontrib-fulltoc 4 | recommonmark 5 | -------------------------------------------------------------------------------- /docs/build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/objects.inv -------------------------------------------------------------------------------- /docs/source/images/ex_nerf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/source/images/ex_nerf.png -------------------------------------------------------------------------------- /docs/build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/quick.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/doctrees/quick.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/svox.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/doctrees/svox.doctree -------------------------------------------------------------------------------- /docs/build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/file.png -------------------------------------------------------------------------------- /docs/build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/build/doctrees/ex_nerf.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/doctrees/ex_nerf.doctree -------------------------------------------------------------------------------- /docs/build/html/_images/ex_nerf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_images/ex_nerf.png -------------------------------------------------------------------------------- /docs/build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/build/doctrees/ex_opt_toy.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/doctrees/ex_opt_toy.doctree -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Inconsolata.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Inconsolata.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab-Bold.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-normal.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-normal.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Inconsolata-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Inconsolata-Bold.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab-Regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-bold-italic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-normal-italic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sxyu/svox/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | python: 4 | version: 3.7 5 | install: 6 | - requirements: requirements.txt 7 | - requirements: docs/requirements.txt 8 | - method: pip 9 | path: . 10 | -------------------------------------------------------------------------------- /docs/build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 6d34bec2426d8559d39195fca2864700 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '0.2.32-dev', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | LINK_SUFFIX: '.html', 9 | HAS_SOURCE: true, 10 | SOURCELINK_SUFFIX: '.txt', 11 | NAVIGATION_WITH_KEYS: false 12 | }; -------------------------------------------------------------------------------- /docs/source/ex_nerf.rst: -------------------------------------------------------------------------------- 1 | Example: Lego Bulldozer Rendering 2 | ====================================== 3 | 4 | In this example, we load a stored PlenOctree npz model file and render it using 5 | VolumeRenderer. 6 | You can download the npz from: 7 | https://drive.google.com/file/d/1XRi_YqdcDrfwqOqV3QPoEOZynuHAGI5M/view?usp=sharing 8 | 9 | .. literalinclude:: ex_nerf.py 10 | :language: python 11 | 12 | .. image:: images/ex_nerf.png 13 | :width: 600 14 | -------------------------------------------------------------------------------- /docs/build/html/_sources/ex_nerf.rst.txt: -------------------------------------------------------------------------------- 1 | Example: Lego Bulldozer Rendering 2 | ====================================== 3 | 4 | In this example, we load a stored PlenOctree npz model file and render it using 5 | VolumeRenderer. 6 | You can download the npz from: 7 | https://drive.google.com/file/d/1XRi_YqdcDrfwqOqV3QPoEOZynuHAGI5M/view?usp=sharing 8 | 9 | .. literalinclude:: ex_nerf.py 10 | :language: python 11 | 12 | .. image:: images/ex_nerf.png 13 | :width: 600 14 | -------------------------------------------------------------------------------- /docs/source/svox.rst: -------------------------------------------------------------------------------- 1 | .. _svox: 2 | 3 | Reference 4 | ============ 5 | 6 | N^3-Tree 7 | ---------------- 8 | 9 | .. autoclass:: svox.N3Tree 10 | :members: 11 | :show-inheritance: 12 | 13 | N^3-Tree View 14 | ---------------- 15 | 16 | .. autoclass:: svox.N3TreeView 17 | :members: 18 | :show-inheritance: 19 | 20 | Differentiable Volume Renderer 21 | ------------------------------- 22 | 23 | .. autoclass:: svox.VolumeRenderer 24 | :members: 25 | :show-inheritance: 26 | -------------------------------------------------------------------------------- /docs/build/html/_sources/svox.rst.txt: -------------------------------------------------------------------------------- 1 | .. _svox: 2 | 3 | Reference 4 | ============ 5 | 6 | N^3-Tree 7 | ---------------- 8 | 9 | .. autoclass:: svox.N3Tree 10 | :members: 11 | :show-inheritance: 12 | 13 | N^3-Tree View 14 | ---------------- 15 | 16 | .. autoclass:: svox.N3TreeView 17 | :members: 18 | :show-inheritance: 19 | 20 | Differentiable Volume Renderer 21 | ------------------------------- 22 | 23 | .. autoclass:: svox.VolumeRenderer 24 | :members: 25 | :show-inheritance: 26 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include LICENSE.txt 3 | include MANIFEST.in 4 | include setup.py 5 | include svox/svox.py 6 | include svox/helpers.py 7 | include svox/sh.py 8 | include svox/renderer.py 9 | include svox/__init__.py 10 | include svox/version.py 11 | include svox/csrc/include/common.cuh 12 | include svox/csrc/include/data_spec.hpp 13 | include svox/csrc/include/data_spec_packed.cuh 14 | include svox/csrc/svox.cpp 15 | include svox/csrc/svox_kernel.cu 16 | include svox/csrc/rt_kernel.cu 17 | include svox/csrc/quantizer.cpp 18 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/source/ex_nerf.py: -------------------------------------------------------------------------------- 1 | import svox 2 | import torch 3 | import matplotlib.pyplot as plt 4 | 5 | device = 'cuda:0' 6 | 7 | t = svox.N3Tree.load("lego.npz", device=device) 8 | r = svox.VolumeRenderer(t) 9 | 10 | # Matrix copied from lego test set image 0 11 | c2w = torch.tensor([[ -0.9999999403953552, 0.0, 0.0, 0.0 ], 12 | [ 0.0, -0.7341099977493286, 0.6790305972099304, 2.737260103225708 ], 13 | [ 0.0, 0.6790306568145752, 0.7341098785400391, 2.959291696548462 ], 14 | [ 0.0, 0.0, 0.0, 1.0 ], 15 | ], device=device) 16 | 17 | with torch.no_grad(): 18 | im = r.render_persp(c2w, height=800, width=800, fx=1111.111).clamp_(0.0, 1.0) 19 | plt.imshow(im.cpu()) 20 | plt.show() 21 | -------------------------------------------------------------------------------- /docs/build/html/_static/js/badge_only.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/ex_opt_toy.py: -------------------------------------------------------------------------------- 1 | import svox 2 | import torch 3 | 4 | device = 'cuda:0' 5 | t = svox.N3Tree(device=device, data_format="SH1") 6 | 7 | t[0, 0, 0, :-1] = 0.0 8 | t[0, 0, 0, -1:] = 0.5 9 | r = svox.VolumeRenderer(t) 10 | 11 | target = torch.tensor([[0.0, 1.0, 0.5]], device=device) 12 | 13 | ray_ori = torch.tensor([[0.1, 0.1, -0.1]], device=device) 14 | ray_dir = torch.tensor([[0.0, 0.0, 1.0]], device=device) 15 | ray = svox.Rays(origins=ray_ori, dirs=ray_dir, viewdirs=ray_dir) 16 | 17 | lr = 1e2 18 | 19 | print('GRADIENT DESC') 20 | 21 | for i in range(20): 22 | rend = r(ray, cuda=True) 23 | if i % 2 == 0: 24 | print(rend.detach()[0].cpu().numpy()) 25 | ((rend - target) ** 2).sum().backward() 26 | t.data.data -= lr * t.data.grad 27 | t.zero_grad() 28 | 29 | print('Expanding..') 30 | t.expand("SH4") 31 | print(r.data_format) 32 | for i in range(20): 33 | rend = r(ray, cuda=True) 34 | if i % 2 == 0: 35 | print(rend.detach()[0].cpu().numpy()) 36 | ((rend - target) ** 2).sum().backward() 37 | t.data.data -= lr * t.data.grad 38 | t.zero_grad() 39 | 40 | print('TARGET') 41 | print(target[0].cpu().numpy()) 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | import os.path as osp 3 | 4 | from torch.utils.cpp_extension import BuildExtension, CUDAExtension 5 | 6 | ROOT_DIR = osp.dirname(osp.abspath(__file__)) 7 | 8 | __version__ = None 9 | exec(open('svox/version.py', 'r').read()) 10 | 11 | CUDA_FLAGS = [] 12 | INSTALL_REQUIREMENTS = [] 13 | 14 | try: 15 | ext_modules = [ 16 | CUDAExtension('svox.csrc', [ 17 | 'svox/csrc/svox.cpp', 18 | 'svox/csrc/svox_kernel.cu', 19 | 'svox/csrc/rt_kernel.cu', 20 | 'svox/csrc/quantizer.cpp', 21 | ], include_dirs=[osp.join(ROOT_DIR, "svox", "csrc", "include")], 22 | optional=True), 23 | ] 24 | except: 25 | import warnings 26 | warnings.warn("Failed to build CUDA extension") 27 | ext_modules = [] 28 | 29 | setup( 30 | name='svox', 31 | version=__version__, 32 | author='Alex Yu', 33 | author_email='alexyu99126@gmail.com', 34 | description='Sparse voxel N^3-tree data structure using CUDA', 35 | long_description='Sparse voxel N^3-tree data structure PyTorch extension, using CUDA', 36 | ext_modules=ext_modules, 37 | setup_requires=['pybind11>=2.5.0'], 38 | packages=['svox', 'svox.csrc'], 39 | cmdclass={'build_ext': BuildExtension}, 40 | zip_safe=False, 41 | ) 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright Alex Yu 2021 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PlenOctrees: PyTorch CUDA Extension 2 | 3 | This repository contains a differentiable PlenOctree and renderer implementation 4 | as a PyTorch CUDA extension. It is used by our conversion and optimization code. 5 | 6 | PlenOctrees for Real Time Rendering of Neural Radiance Fields
7 | Alex Yu, Ruilong Li, Matthew Tancik, Hao Li, Ren Ng, Angjoo Kanazawa 8 | 9 | https://alexyu.net/plenoctrees 10 | 11 | ``` 12 | @inproceedings{yu2021plenoctrees, 13 | title={{PlenOctrees} for Real-time Rendering of Neural Radiance Fields}, 14 | author={Alex Yu and Ruilong Li and Matthew Tancik and Hao Li and Ren Ng and Angjoo Kanazawa}, 15 | year={2021}, 16 | booktitle={ICCV}, 17 | } 18 | ``` 19 | 20 | Please also refer to the following repositories 21 | 22 | - NeRF-SH training and PlenOctree extraction: 23 | - C++ volume renderer 24 | 25 | ## Installation 26 | `pip install svox` 27 | 28 | ## Documentation 29 | Please see 30 | 31 | ## Troubleshooting 32 | If you get SIGSEGV upon importing, 33 | check that your CUDA runtime and PyTorch CUDA versions match. That is, 34 | `nvcc --version` 35 | should match (Python) 36 | `torch.version.cuda` 37 | 38 | ## Misc 39 | SVOX stands for **s**parse **v**oxel **o**ctree e**x**tension. 40 | -------------------------------------------------------------------------------- /svox/version.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 PlenOctree Authors. 2 | # 3 | # Redistribution and use in source and binary forms, with or without 4 | # modification, are permitted provided that the following conditions are met: 5 | # 6 | # 1. Redistributions of source code must retain the above copyright notice, 7 | # this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | # POSSIBILITY OF SUCH DAMAGE. 24 | 25 | __version__ = '0.2.32' 26 | -------------------------------------------------------------------------------- /svox/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | CUDA accelerated PyTorch N^3 tree library. 3 | """ 4 | 5 | # Copyright 2021 PlenOctree Authors. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | # POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from .version import __version__ 30 | 31 | from .svox import N3Tree 32 | from .renderer import VolumeRenderer, NDCConfig, Rays 33 | from .helpers import N3TreeView, LocalIndex 34 | -------------------------------------------------------------------------------- /docs/source/ex_opt_toy.rst: -------------------------------------------------------------------------------- 1 | Example: Optimization and expand 2 | ====================================== 3 | 4 | In this example, we optimize a tiny octree's output to the 5 | RGB color vector :code:`[0, 1, 0.5]`, for a fixed ray. 6 | 7 | We start with data format SH1 and in the middle switch to SH4 using the :code:`expand(format)` function, 8 | which automatically inserts extra channels as appropriate. 9 | Then we continue to optimize using a manual gradient descent with MSE. 10 | Slowly, the results get closer to the target vector. 11 | 12 | 13 | .. literalinclude:: ex_opt_toy.py 14 | :language: python 15 | 16 | The output: 17 | 18 | .. code:: 19 | 20 | GRADIENT DESC 21 | [0.88920575 0.88920575 0.88920575] 22 | [0.67369866 0.6859846 0.67984015] 23 | [0.6194525 0.65586865 0.63762873] 24 | [0.58019906 0.64437073 0.61214054] 25 | [0.5475207 0.6409838 0.59386927] 26 | [0.5188446 0.6420485 0.579674 ] 27 | [0.49309036 0.64582 0.5681365 ] 28 | [0.46970066 0.6513118 0.55849427] 29 | [0.4483344 0.657904 0.5502867] 30 | [0.42875046 0.66518104 0.54321104] 31 | Expanding.. 32 | SH4 33 | [0.4107593 0.6728529 0.5370555] 34 | [0.3631369 0.71049845 0.5277597 ] 35 | [0.32639033 0.7405325 0.52003586] 36 | [0.29751268 0.7646569 0.51378375] 37 | [0.27432522 0.7842779 0.5088086 ] 38 | [0.25531954 0.80046684 0.50490075] 39 | [0.23945224 0.8140159 0.50186735] 40 | [0.22599061 0.8255081 0.4995423 ] 41 | [0.21440998 0.83537465 0.4977861 ] 42 | [0.2043267 0.84393847 0.49648416] 43 | TARGET 44 | [0. 1. 0.5] 45 | 46 | -------------------------------------------------------------------------------- /docs/build/html/_sources/ex_opt_toy.rst.txt: -------------------------------------------------------------------------------- 1 | Example: Optimization and expand 2 | ====================================== 3 | 4 | In this example, we optimize a tiny octree's output to the 5 | RGB color vector :code:`[0, 1, 0.5]`, for a fixed ray. 6 | 7 | We start with data format SH1 and in the middle switch to SH4 using the :code:`expand(format)` function, 8 | which automatically inserts extra channels as appropriate. 9 | Then we continue to optimize using a manual gradient descent with MSE. 10 | Slowly, the results get closer to the target vector. 11 | 12 | 13 | .. literalinclude:: ex_opt_toy.py 14 | :language: python 15 | 16 | The output: 17 | 18 | .. code:: 19 | 20 | GRADIENT DESC 21 | [0.88920575 0.88920575 0.88920575] 22 | [0.67369866 0.6859846 0.67984015] 23 | [0.6194525 0.65586865 0.63762873] 24 | [0.58019906 0.64437073 0.61214054] 25 | [0.5475207 0.6409838 0.59386927] 26 | [0.5188446 0.6420485 0.579674 ] 27 | [0.49309036 0.64582 0.5681365 ] 28 | [0.46970066 0.6513118 0.55849427] 29 | [0.4483344 0.657904 0.5502867] 30 | [0.42875046 0.66518104 0.54321104] 31 | Expanding.. 32 | SH4 33 | [0.4107593 0.6728529 0.5370555] 34 | [0.3631369 0.71049845 0.5277597 ] 35 | [0.32639033 0.7405325 0.52003586] 36 | [0.29751268 0.7646569 0.51378375] 37 | [0.27432522 0.7842779 0.5088086 ] 38 | [0.25531954 0.80046684 0.50490075] 39 | [0.23945224 0.8140159 0.50186735] 40 | [0.22599061 0.8255081 0.4995423 ] 41 | [0.21440998 0.83537465 0.4977861 ] 42 | [0.2043267 0.84393847 0.49648416] 43 | TARGET 44 | [0. 1. 0.5] 45 | 46 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. svox documentation master file, created by 2 | sphinx-quickstart on Wed Feb 17 23:40:50 2021. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to the svox documentation 7 | ====================================================== 8 | 9 | This is a PlenOctree volume rendering implementation as a PyTorch extension with CUDA acceleration. 10 | 11 | Note this only implements octree (or more generally N^3 tree) operations and differentiable volume rendering. It *does not* relate to NeRF training part of the project 12 | and does not involve a neural network. 13 | 14 | The code is available in `this repo `_. 15 | This is part of the code release of 16 | 17 | | PlenOctrees for Real Time Rendering of Neural Radiance Fields 18 | | Alex Yu, Ruilong Li, Matthew Tancik, Hao Li, Ren Ng, Angjoo Kanazawa 19 | 20 | | Paper: `https://arxiv.org/abs/2103.14024 `_ 21 | | Website: `https://alexyu.net/plenoctrees `_ 22 | | Source code (SVOX): `https://github.com/sxyu/svox `_ 23 | 24 | Install with :code:`pip install svox`. 25 | 26 | >>> import svox 27 | >>> tree = svox.N3Tree(data_dim=4) 28 | >>> print(tree) 29 | svox.N3Tree(N=2, data_dim=4, depth_limit=10; capacity:1/1 max_depth:0) 30 | >>> tree.to('cuda:0') 31 | 32 | 33 | :code:`data_dim` is the size of data stored at each leaf. 34 | 35 | Please see :ref:`svox` for detailed per-method documentation and :ref:`quick` for a quick overview of features. 36 | This is the documentation of svox version: |version| |release|. 37 | 38 | 39 | .. toctree:: 40 | :maxdepth: 2 41 | :caption: Contents: 42 | 43 | quick 44 | svox 45 | ex_nerf 46 | ex_opt_toy 47 | -------------------------------------------------------------------------------- /docs/build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. svox documentation master file, created by 2 | sphinx-quickstart on Wed Feb 17 23:40:50 2021. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to the svox documentation 7 | ====================================================== 8 | 9 | This is a PlenOctree volume rendering implementation as a PyTorch extension with CUDA acceleration. 10 | 11 | Note this only implements octree (or more generally N^3 tree) operations and differentiable volume rendering. It *does not* relate to NeRF training part of the project 12 | and does not involve a neural network. 13 | 14 | The code is available in `this repo `_. 15 | This is part of the code release of 16 | 17 | | PlenOctrees for Real Time Rendering of Neural Radiance Fields 18 | | Alex Yu, Ruilong Li, Matthew Tancik, Hao Li, Ren Ng, Angjoo Kanazawa 19 | 20 | | Paper: `https://arxiv.org/abs/2103.14024 `_ 21 | | Website: `https://alexyu.net/plenoctrees `_ 22 | | Source code (SVOX): `https://github.com/sxyu/svox `_ 23 | 24 | Install with :code:`pip install svox`. 25 | 26 | >>> import svox 27 | >>> tree = svox.N3Tree(data_dim=4) 28 | >>> print(tree) 29 | svox.N3Tree(N=2, data_dim=4, depth_limit=10; capacity:1/1 max_depth:0) 30 | >>> tree.to('cuda:0') 31 | 32 | 33 | :code:`data_dim` is the size of data stored at each leaf. 34 | 35 | Please see :ref:`svox` for detailed per-method documentation and :ref:`quick` for a quick overview of features. 36 | This is the documentation of svox version: |version| |release|. 37 | 38 | 39 | .. toctree:: 40 | :maxdepth: 2 41 | :caption: Contents: 42 | 43 | quick 44 | svox 45 | ex_nerf 46 | ex_opt_toy 47 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | import sphinx_rtd_theme 16 | from svox import __version__ 17 | sys.path.insert(0, os.path.join(os.path.abspath('.'), '..')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = 'svox' 23 | copyright = '2021 Alex Yu' 24 | author = 'Alex Yu' 25 | 26 | # The full version, including alpha/beta/rc tags 27 | release = __version__ 28 | 29 | 30 | # -- General configuration --------------------------------------------------- 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = [ 36 | 'recommonmark', 37 | 'sphinx.ext.autodoc', 38 | 'sphinx_rtd_theme', 39 | ] 40 | 41 | # Add any paths that contain templates here, relative to this directory. 42 | templates_path = ['_templates'] 43 | 44 | # List of patterns, relative to source directory, that match files and 45 | # directories to ignore when looking for source files. 46 | # This pattern also affects html_static_path and html_extra_path. 47 | exclude_patterns = [] 48 | 49 | 50 | # -- Options for HTML output ------------------------------------------------- 51 | 52 | # The theme to use for HTML and HTML Help pages. See the documentation for 53 | # a list of builtin themes. 54 | # 55 | html_theme = 'sphinx_rtd_theme' 56 | 57 | # Add any paths that contain custom static files (such as style sheets) here, 58 | # relative to this directory. They are copied after the builtin static files, 59 | # so a file named "default.css" will overwrite the builtin "default.css". 60 | html_static_path = [] 61 | 62 | add_module_names = False 63 | 64 | def skip(app, what, name, obj, would_skip, options): 65 | if name == "__init__": 66 | return False 67 | return would_skip 68 | 69 | def setup(app): 70 | app.connect("autodoc-skip-member", skip) 71 | 72 | autodoc_member_order = 'bysource' 73 | 74 | html_theme_options = { 75 | 'collapse_navigation': False, 76 | 'sticky_navigation': True, 77 | } 78 | -------------------------------------------------------------------------------- /docs/build/html/_static/js/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/build/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} -------------------------------------------------------------------------------- /svox/csrc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2021 PlenOctree Authors. 2 | # 3 | # Redistribution and use in source and binary forms, with or without 4 | # modification, are permitted provided that the following conditions are met: 5 | # 6 | # 1. Redistributions of source code must retain the above copyright notice, 7 | # this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | # POSSIBILITY OF SUCH DAMAGE. 24 | 25 | # NOTE: This CMakeLists is for development purposes only 26 | # (To check CUDA compile errors) 27 | # It is NOT necessary to use this for installation. Just use pip install . 28 | cmake_minimum_required( VERSION 3.3 ) 29 | 30 | if(NOT CMAKE_BUILD_TYPE) 31 | set(CMAKE_BUILD_TYPE Release) 32 | endif() 33 | if (POLICY CMP0048) 34 | cmake_policy(SET CMP0048 NEW) 35 | endif (POLICY CMP0048) 36 | if (POLICY CMP0069) 37 | cmake_policy(SET CMP0069 NEW) 38 | endif (POLICY CMP0069) 39 | if (POLICY CMP0072) 40 | cmake_policy(SET CMP0072 NEW) 41 | endif (POLICY CMP0072) 42 | 43 | project( svox ) 44 | 45 | enable_language(CUDA) 46 | message(STATUS "CUDA enabled") 47 | set( CMAKE_CUDA_STANDARD 14 ) 48 | set( CMAKE_CUDA_STANDARD_REQUIRED ON) 49 | set( CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -g -Xcudafe \"--display_error_number --diag_suppress=3057 --diag_suppress=3058 --diag_suppress=3059 --diag_suppress=3060\" -lineinfo -arch=sm_61") 50 | 51 | set( INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" ) 52 | 53 | if( MSVC ) 54 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") 55 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /GLT /Ox") 56 | set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -Xcompiler=\"/MT\"" ) 57 | endif() 58 | 59 | file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/*.cu) 60 | 61 | find_package(pybind11 REQUIRED) 62 | find_package(Torch REQUIRED) 63 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") 64 | 65 | include_directories (${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) 66 | 67 | pybind11_add_module(svox-test SHARED ${SOURCES}) 68 | target_link_libraries(svox-test PRIVATE "${TORCH_LIBRARIES}") 69 | target_include_directories(svox-test PRIVATE "${INCLUDE_DIR}") 70 | 71 | if (MSVC) 72 | file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll") 73 | add_custom_command(TARGET svox-test 74 | POST_BUILD 75 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 76 | ${TORCH_DLLS} 77 | $) 78 | endif (MSVC) 79 | -------------------------------------------------------------------------------- /svox/csrc/include/data_spec.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 PlenOctree Authors 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #define DEVICE_GUARD(_ten) \ 34 | const at::cuda::OptionalCUDAGuard device_guard(device_of(_ten)); 35 | 36 | // Changed from x.type().is_cuda() due to deprecation 37 | #define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x " must be a CUDA tensor") 38 | #define CHECK_CONTIGUOUS(x) \ 39 | TORCH_CHECK(x.is_contiguous(), #x " must be contiguous") 40 | #define CHECK_INPUT(x) \ 41 | CHECK_CUDA(x); \ 42 | CHECK_CONTIGUOUS(x) 43 | 44 | enum DataFormat { 45 | FORMAT_RGBA, 46 | FORMAT_SH, 47 | FORMAT_SG, 48 | FORMAT_ASG, 49 | }; 50 | 51 | struct RaysSpec { 52 | torch::Tensor origins; 53 | torch::Tensor dirs; 54 | torch::Tensor vdirs; 55 | 56 | inline void check() { 57 | CHECK_INPUT(origins); 58 | CHECK_INPUT(dirs); 59 | CHECK_INPUT(vdirs); 60 | TORCH_CHECK(origins.is_floating_point()); 61 | TORCH_CHECK(dirs.is_floating_point()); 62 | TORCH_CHECK(vdirs.is_floating_point()); 63 | } 64 | }; 65 | 66 | struct TreeSpec { 67 | torch::Tensor data; 68 | torch::Tensor child; 69 | torch::Tensor parent_depth; 70 | torch::Tensor extra_data; 71 | torch::Tensor offset; 72 | torch::Tensor scaling; 73 | torch::Tensor _weight_accum; 74 | bool _weight_accum_max; 75 | 76 | inline void check() { 77 | CHECK_INPUT(data); 78 | CHECK_INPUT(child); 79 | CHECK_INPUT(parent_depth); 80 | if (extra_data.numel()) { 81 | CHECK_INPUT(extra_data); 82 | } 83 | CHECK_INPUT(offset); 84 | CHECK_INPUT(scaling); 85 | if (_weight_accum.numel()) { 86 | CHECK_INPUT(_weight_accum); 87 | } 88 | } 89 | }; 90 | 91 | struct CameraSpec { 92 | torch::Tensor c2w; 93 | float fx; 94 | float fy; 95 | int width; 96 | int height; 97 | 98 | inline void check() { 99 | CHECK_INPUT(c2w); 100 | TORCH_CHECK(c2w.is_floating_point()); 101 | TORCH_CHECK(c2w.ndimension() == 2); 102 | TORCH_CHECK(c2w.size(1) == 4); 103 | } 104 | }; 105 | 106 | // CUDA-ready 107 | struct RenderOptions { 108 | float step_size; 109 | float background_brightness; 110 | 111 | int format; 112 | int basis_dim; 113 | 114 | int ndc_width; 115 | int ndc_height; 116 | float ndc_focal; 117 | 118 | int min_comp; 119 | int max_comp; 120 | 121 | float sigma_thresh; 122 | float stop_thresh; 123 | 124 | bool density_softplus; 125 | float rgb_padding; 126 | }; 127 | 128 | using QueryResult = std::tuple; 129 | -------------------------------------------------------------------------------- /docs/build/html/_static/js/html5shiv-printshiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /svox/csrc/include/data_spec_packed.cuh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 PlenOctree Authors 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | #include "data_spec.hpp" 29 | 30 | template 31 | struct SingleRaySpec { 32 | const scalar_t* __restrict__ origin; 33 | scalar_t* __restrict__ dir; 34 | const scalar_t* __restrict__ vdir; 35 | }; 36 | 37 | template 38 | struct PackedRaysSpec { 39 | PackedRaysSpec(RaysSpec& ray) : 40 | origins(ray.origins.packed_accessor32()), 41 | vdirs(ray.vdirs.packed_accessor32()), 42 | dirs(ray.dirs.packed_accessor32()) { } 43 | 44 | const torch::PackedTensorAccessor32 45 | origins; 46 | const torch::PackedTensorAccessor32 47 | dirs; 48 | const torch::PackedTensorAccessor32 49 | vdirs; 50 | 51 | SingleRaySpec operator[](int32_t i) { 52 | return SingleRaySpec{&origins[i][0], &dirs[i][0], &vdirs[i][0]}; 53 | } 54 | }; 55 | 56 | template 57 | struct PackedTreeSpec { 58 | PackedTreeSpec(TreeSpec& tree) : 59 | data(tree.data.packed_accessor64()), 60 | child(tree.child.packed_accessor32()), 61 | parent_depth(tree.parent_depth.packed_accessor32()), 62 | extra_data(tree.extra_data.packed_accessor32()), 63 | offset(tree.offset.data()), 64 | scaling(tree.scaling.data()), 65 | weight_accum(tree._weight_accum.numel() > 0 ? tree._weight_accum.data() : nullptr), 66 | weight_accum_max(tree._weight_accum_max) 67 | { } 68 | 69 | torch::PackedTensorAccessor64 70 | data; 71 | const torch::PackedTensorAccessor32 72 | child; 73 | const torch::PackedTensorAccessor32 74 | parent_depth; 75 | torch::PackedTensorAccessor32 76 | extra_data; 77 | const scalar_t* __restrict__ offset; 78 | const scalar_t* __restrict__ scaling; 79 | scalar_t* __restrict__ weight_accum; 80 | bool weight_accum_max; 81 | }; 82 | 83 | template 84 | struct PackedCameraSpec { 85 | PackedCameraSpec(CameraSpec& cam) : 86 | c2w(cam.c2w.packed_accessor32()), 87 | fx(cam.fx), fy(cam.fy), width(cam.width), height(cam.height) {} 88 | const torch::PackedTensorAccessor32 89 | c2w; 90 | float fx; 91 | float fy; 92 | int width; 93 | int height; 94 | }; 95 | -------------------------------------------------------------------------------- /docs/build/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | !function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}t.length>0&&($(".wy-menu-vertical .current").removeClass("current"),t.addClass("current"),t.closest("li.toctree-l1").addClass("current"),t.closest("li.toctree-l1").parent().addClass("current"),t.closest("li.toctree-l1").addClass("current"),t.closest("li.toctree-l2").addClass("current"),t.closest("li.toctree-l3").addClass("current"),t.closest("li.toctree-l4").addClass("current"),t.closest("li.toctree-l5").addClass("current"),t[0].scrollIntoView())}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t 30 | #include 31 | #include 32 | 33 | #include "data_spec.hpp" 34 | 35 | namespace py = pybind11; 36 | using torch::Tensor; 37 | 38 | std::vector grid_weight_render(torch::Tensor data, 39 | CameraSpec& cam, 40 | RenderOptions& opt, 41 | torch::Tensor offset, 42 | torch::Tensor scaling); 43 | 44 | QueryResult query_vertical(TreeSpec&, Tensor); 45 | Tensor query_vertical_backward(TreeSpec&, Tensor, Tensor); 46 | void assign_vertical(TreeSpec&, Tensor, Tensor); 47 | 48 | Tensor volume_render(TreeSpec&, RaysSpec&, RenderOptions&); 49 | Tensor volume_render_image(TreeSpec&, CameraSpec&, RenderOptions&); 50 | Tensor volume_render_backward(TreeSpec&, RaysSpec&, RenderOptions&, Tensor); 51 | Tensor volume_render_image_backward(TreeSpec&, CameraSpec&, RenderOptions&, 52 | Tensor); 53 | 54 | std::tuple se_grad(TreeSpec&, RaysSpec&, Tensor, 55 | RenderOptions&); 56 | std::tuple se_grad_persp(TreeSpec&, CameraSpec&, 57 | RenderOptions&, Tensor); 58 | 59 | Tensor calc_corners(TreeSpec&, Tensor); 60 | 61 | std::tuple quantize_median_cut(Tensor data, Tensor, int32_t); 62 | 63 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 64 | py::class_(m, "RaysSpec") 65 | .def(py::init<>()) 66 | .def_readwrite("origins", &RaysSpec::origins) 67 | .def_readwrite("dirs", &RaysSpec::dirs) 68 | .def_readwrite("vdirs", &RaysSpec::vdirs); 69 | 70 | py::class_(m, "TreeSpec") 71 | .def(py::init<>()) 72 | .def_readwrite("data", &TreeSpec::data) 73 | .def_readwrite("child", &TreeSpec::child) 74 | .def_readwrite("parent_depth", &TreeSpec::parent_depth) 75 | .def_readwrite("extra_data", &TreeSpec::extra_data) 76 | .def_readwrite("offset", &TreeSpec::offset) 77 | .def_readwrite("scaling", &TreeSpec::scaling) 78 | .def_readwrite("_weight_accum", &TreeSpec::_weight_accum) 79 | .def_readwrite("_weight_accum_max", &TreeSpec::_weight_accum_max); 80 | 81 | py::class_(m, "CameraSpec") 82 | .def(py::init<>()) 83 | .def_readwrite("c2w", &CameraSpec::c2w) 84 | .def_readwrite("fx", &CameraSpec::fx) 85 | .def_readwrite("fy", &CameraSpec::fy) 86 | .def_readwrite("width", &CameraSpec::width) 87 | .def_readwrite("height", &CameraSpec::height); 88 | 89 | py::class_(m, "RenderOptions") 90 | .def(py::init<>()) 91 | .def_readwrite("step_size", &RenderOptions::step_size) 92 | .def_readwrite("background_brightness", 93 | &RenderOptions::background_brightness) 94 | .def_readwrite("ndc_width", &RenderOptions::ndc_width) 95 | .def_readwrite("ndc_height", &RenderOptions::ndc_height) 96 | .def_readwrite("ndc_focal", &RenderOptions::ndc_focal) 97 | .def_readwrite("format", &RenderOptions::format) 98 | .def_readwrite("basis_dim", &RenderOptions::basis_dim) 99 | .def_readwrite("min_comp", &RenderOptions::min_comp) 100 | .def_readwrite("max_comp", &RenderOptions::max_comp) 101 | .def_readwrite("sigma_thresh", &RenderOptions::sigma_thresh) 102 | .def_readwrite("stop_thresh", &RenderOptions::stop_thresh) 103 | .def_readwrite("density_softplus", &RenderOptions::density_softplus) 104 | .def_readwrite("rgb_padding", &RenderOptions::rgb_padding); 105 | 106 | m.def("query_vertical", &query_vertical); 107 | m.def("query_vertical_backward", &query_vertical_backward); 108 | m.def("assign_vertical", &assign_vertical); 109 | 110 | m.def("volume_render", &volume_render); 111 | m.def("volume_render_image", &volume_render_image); 112 | m.def("volume_render_backward", &volume_render_backward); 113 | m.def("volume_render_image_backward", &volume_render_image_backward); 114 | 115 | m.def("se_grad", &se_grad); 116 | m.def("se_grad_persp", &se_grad_persp); 117 | 118 | m.def("calc_corners", &calc_corners); 119 | 120 | m.def("grid_weight_render", &grid_weight_render); 121 | m.def("quantize_median_cut", &quantize_median_cut); 122 | } 123 | -------------------------------------------------------------------------------- /svox/csrc/include/common.cuh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 PlenOctree Authors 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | namespace { 34 | namespace device { 35 | 36 | template 37 | __device__ __inline__ void clamp_coord(scalar_t* __restrict__ q) { 38 | for (int i = 0; i < 3; ++i) { 39 | q[i] = max(scalar_t(0.0), min(scalar_t(1.0) - 1e-6, q[i])); 40 | } 41 | } 42 | 43 | template 44 | __device__ __inline__ void transform_coord(scalar_t* __restrict__ q, 45 | const scalar_t* __restrict__ offset, 46 | const scalar_t* __restrict__ scaling) { 47 | for (int i = 0; i < 3; ++i) { 48 | q[i] = offset[i] + scaling[i] * q[i]; 49 | } 50 | } 51 | 52 | template 53 | __device__ __inline__ scalar_t* query_single_from_root( 54 | torch::PackedTensorAccessor64 55 | data, 56 | const torch::PackedTensorAccessor32 57 | child, 58 | scalar_t* __restrict__ xyz_inout, 59 | scalar_t* __restrict__ cube_sz_out, 60 | int64_t* __restrict__ node_id_out=nullptr) { 61 | const scalar_t N = child.size(1); 62 | clamp_coord(xyz_inout); 63 | 64 | int32_t node_id = 0; 65 | int32_t u, v, w; 66 | *cube_sz_out = N; 67 | while (true) { 68 | xyz_inout[0] *= N; 69 | xyz_inout[1] *= N; 70 | xyz_inout[2] *= N; 71 | u = floor(xyz_inout[0]); 72 | v = floor(xyz_inout[1]); 73 | w = floor(xyz_inout[2]); 74 | xyz_inout[0] -= u; 75 | xyz_inout[1] -= v; 76 | xyz_inout[2] -= w; 77 | 78 | const int32_t skip = child[node_id][u][v][w]; 79 | if (skip == 0) { 80 | if (node_id_out != nullptr) { 81 | *node_id_out = node_id * int64_t(N * N * N) + 82 | u * int32_t(N * N) + v * int32_t(N) + w; 83 | } 84 | return &data[node_id][u][v][w][0]; 85 | } 86 | *cube_sz_out *= N; 87 | node_id += skip; 88 | } 89 | return nullptr; 90 | } 91 | 92 | } // namespace device 93 | } // namespace 94 | 95 | #define CUDA_GET_THREAD_ID(tid, Q) const int tid = blockIdx.x * blockDim.x + threadIdx.x; \ 96 | if (tid >= Q) return 97 | #define CUDA_N_BLOCKS_NEEDED(Q, CUDA_N_THREADS) ((Q - 1) / CUDA_N_THREADS + 1) 98 | #define CUDA_CHECK_ERRORS \ 99 | cudaError_t err = cudaGetLastError(); \ 100 | if (err != cudaSuccess) \ 101 | printf("Error in svox.%s : %s\n", __FUNCTION__, cudaGetErrorString(err)) 102 | 103 | namespace { 104 | // Get approx number of CUDA cores 105 | __host__ int get_sp_cores(cudaDeviceProp devProp) { 106 | int cores = 0; 107 | int mp = devProp.multiProcessorCount; 108 | switch (devProp.major){ 109 | case 2: // Fermi 110 | if (devProp.minor == 1) cores = mp * 48; 111 | else cores = mp * 32; 112 | break; 113 | case 3: // Kepler 114 | cores = mp * 192; 115 | break; 116 | case 5: // Maxwell 117 | cores = mp * 128; 118 | break; 119 | case 6: // Pascal 120 | if ((devProp.minor == 1) || (devProp.minor == 2)) cores = mp * 128; 121 | else if (devProp.minor == 0) cores = mp * 64; 122 | break; 123 | case 7: // Volta and Turing 124 | if ((devProp.minor == 0) || (devProp.minor == 5)) cores = mp * 64; 125 | break; 126 | case 8: // Ampere 127 | if (devProp.minor == 0) cores = mp * 64; 128 | else if (devProp.minor == 6) cores = mp * 128; 129 | break; 130 | default: 131 | break; 132 | } 133 | return cores; 134 | } 135 | } // namespace 136 | 137 | 138 | #if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 600 139 | #else 140 | __device__ inline double atomicAdd(double* address, double val){ 141 | unsigned long long int* address_as_ull = (unsigned long long int*)address; 142 | unsigned long long int old = *address_as_ull, assumed; 143 | do { 144 | assumed = old; 145 | old = atomicCAS(address_as_ull, assumed, 146 | __double_as_longlong(val + __longlong_as_double(assumed))); 147 | } while (assumed != old); 148 | return __longlong_as_double(old); 149 | } 150 | #endif 151 | 152 | __device__ inline void atomicMax(float* result, float value){ 153 | unsigned* result_as_u = (unsigned*)result; 154 | unsigned old = *result_as_u, assumed; 155 | do { 156 | assumed = old; 157 | old = atomicCAS(result_as_u, assumed, 158 | __float_as_int(fmaxf(value, __int_as_float(assumed)))); 159 | } while (old != assumed); 160 | return; 161 | } 162 | 163 | __device__ inline void atomicMax(double* result, double value){ 164 | unsigned long long int* result_as_ull = (unsigned long long int*)result; 165 | unsigned long long int old = *result_as_ull, assumed; 166 | do { 167 | assumed = old; 168 | old = atomicCAS(result_as_ull, assumed, 169 | __double_as_longlong(fmaxf(value, __longlong_as_double(assumed)))); 170 | } while (old != assumed); 171 | return; 172 | } 173 | -------------------------------------------------------------------------------- /svox/csrc/quantizer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 PlenOctree Authors 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace { 36 | 37 | template 38 | struct Comparer { 39 | Comparer(const torch::TensorAccessor data) : data(data) {} 40 | bool operator()(int64_t a, int64_t b) const { 41 | return data[a][dim] < data[b][dim]; 42 | } 43 | const torch::TensorAccessor data; 44 | int dim; 45 | }; 46 | 47 | template 48 | void _quantize_median_cut_impl( 49 | const torch::TensorAccessor data, 50 | const torch::TensorAccessor weights, 51 | std::vector& tmp_rev_map, 52 | torch::TensorAccessor colors_out, 53 | torch::TensorAccessor color_id_map_out, int32_t order, 54 | int64_t l, int64_t r, int32_t& color_idx, Comparer& comp) { 55 | const int K = data.size(1); 56 | scalar_t total_weight = 0.0; 57 | const bool use_weights = weights.size(0) > 0; 58 | if (order <= 0 || r - l <= 1) { 59 | torch::TensorAccessor color = colors_out[color_idx]; 60 | for (int i = l; i < r; ++i) { 61 | const int64_t ii = tmp_rev_map[i]; 62 | for (int j = 0; j < K; ++j) { 63 | scalar_t entry = data[ii][j]; 64 | if (use_weights) entry *= weights[ii]; 65 | color[j] += entry; 66 | } 67 | if (use_weights) total_weight += weights[ii]; 68 | color_id_map_out[ii] = color_idx; 69 | } 70 | if (!use_weights) { 71 | total_weight = r - l; 72 | } 73 | // std::nth_element(tmp_rev_map.data() + l, tmp_rev_map.data() + m, 74 | // tmp_rev_map.data() + r, comp); 75 | for (int j = 0; j < K; ++j) { 76 | color[j] /= total_weight; 77 | } 78 | ++color_idx; 79 | } else { 80 | const scalar_t MAX_VAL = std::numeric_limits::max(); 81 | comp.dim = 0; 82 | { 83 | std::vector mins(K, MAX_VAL), maxs(K, -MAX_VAL); 84 | for (int i = l; i < r; ++i) { 85 | const int64_t ii = tmp_rev_map[i]; 86 | if (use_weights) total_weight += weights[ii]; 87 | for (int j = 0; j < K; ++j) { 88 | const scalar_t val = data[ii][j]; 89 | maxs[j] = std::max(maxs[j], val); 90 | mins[j] = std::min(mins[j], val); 91 | } 92 | } 93 | scalar_t largest_var = -1.0; 94 | for (int j = 0; j < K; ++j) { 95 | if (maxs[j] - mins[j] > largest_var) { 96 | comp.dim = j; 97 | largest_var = maxs[j] - mins[j]; 98 | } 99 | } 100 | } 101 | 102 | int64_t m; 103 | if (!use_weights) { 104 | m = l + (r - l) / 2; 105 | std::nth_element(tmp_rev_map.data() + l, tmp_rev_map.data() + m, 106 | tmp_rev_map.data() + r, comp); 107 | } else { 108 | std::sort(tmp_rev_map.data() + l, tmp_rev_map.data() + r, comp); 109 | scalar_t pfxsum = 0.0; 110 | for (m = l; m < r; ++m) { 111 | pfxsum += weights[tmp_rev_map[m]]; 112 | if (pfxsum > total_weight * 0.5) { 113 | break; 114 | } 115 | } 116 | } 117 | 118 | _quantize_median_cut_impl(data, weights, tmp_rev_map, colors_out, 119 | color_id_map_out, order - 1, l, m, color_idx, 120 | comp); 121 | _quantize_median_cut_impl(data, weights, tmp_rev_map, colors_out, 122 | color_id_map_out, order - 1, m, r, color_idx, 123 | comp); 124 | } 125 | } 126 | 127 | } // namespace 128 | 129 | std::tuple quantize_median_cut( 130 | torch::Tensor data, torch::Tensor weights, int32_t order) { 131 | TORCH_CHECK(data.is_contiguous()); 132 | TORCH_CHECK(weights.is_contiguous()); 133 | TORCH_CHECK(!data.is_cuda()); 134 | TORCH_CHECK(order < 31); 135 | TORCH_CHECK(data.dim() == 2); 136 | const int32_t N_COLORS = 1 << order; 137 | TORCH_CHECK(N_COLORS <= data.size(0)); 138 | auto options = at::TensorOptions() 139 | .dtype(at::kInt) 140 | .layout(data.layout()) 141 | .device(data.device()); 142 | torch::Tensor colors = 143 | torch::zeros({N_COLORS, data.size(1)}, data.options()); 144 | torch::Tensor color_id_map = torch::zeros({data.size(0)}, options); 145 | std::vector tmp(data.size(0)); 146 | std::iota(tmp.begin(), tmp.end(), 0); 147 | AT_DISPATCH_FLOATING_TYPES(data.type(), __FUNCTION__, [&] { 148 | int32_t color_idx = 0; 149 | Comparer comp(data.accessor()); 150 | _quantize_median_cut_impl( 151 | comp.data, weights.accessor(), tmp, 152 | colors.accessor(), color_id_map.accessor(), 153 | order, 0, data.size(0), color_idx, comp); 154 | }); 155 | return std::template tuple(colors, 156 | color_id_map); 157 | } 158 | -------------------------------------------------------------------------------- /docs/build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Search — svox 0.2.32-dev documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 116 | 117 |
118 | 119 | 120 | 126 | 127 | 128 |
129 | 130 |
131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |
151 | 152 |
    153 | 154 |
  • »
  • 155 | 156 |
  • Search
  • 157 | 158 | 159 |
  • 160 | 161 |
  • 162 | 163 |
164 | 165 | 166 |
167 |
168 |
169 |
170 | 171 | 178 | 179 | 180 |
181 | 182 |
183 | 184 |
185 | 186 |
187 |
188 | 189 |
190 | 191 |
192 |

193 | © Copyright 2021 Alex Yu. 194 | 195 |

196 |
197 | 198 | 199 | 200 | Built with Sphinx using a 201 | 202 | theme 203 | 204 | provided by Read the Docs. 205 | 206 |
207 |
208 |
209 | 210 |
211 | 212 |
213 | 214 | 215 | 220 | 221 | 222 | 223 | 224 | 225 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /svox/sh.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 PlenOctree Authors. 2 | # 3 | # Redistribution and use in source and binary forms, with or without 4 | # modification, are permitted provided that the following conditions are met: 5 | # 6 | # 1. Redistributions of source code must retain the above copyright notice, 7 | # this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | # POSSIBILITY OF SUCH DAMAGE. 24 | 25 | import torch 26 | 27 | C0 = 0.28209479177387814 28 | C1 = 0.4886025119029199 29 | C2 = [ 30 | 1.0925484305920792, 31 | -1.0925484305920792, 32 | 0.31539156525252005, 33 | -1.0925484305920792, 34 | 0.5462742152960396 35 | ] 36 | C3 = [ 37 | -0.5900435899266435, 38 | 2.890611442640554, 39 | -0.4570457994644658, 40 | 0.3731763325901154, 41 | -0.4570457994644658, 42 | 1.445305721320277, 43 | -0.5900435899266435 44 | ] 45 | C4 = [ 46 | 2.5033429417967046, 47 | -1.7701307697799304, 48 | 0.9461746957575601, 49 | -0.6690465435572892, 50 | 0.10578554691520431, 51 | -0.6690465435572892, 52 | 0.47308734787878004, 53 | -1.7701307697799304, 54 | 0.6258357354491761, 55 | ] 56 | 57 | def eval_sh(deg, sh, dirs): 58 | """ 59 | Evaluate spherical harmonics at unit directions 60 | using hardcoded SH polynomials. 61 | Works with torch/np/jnp. 62 | ... Can be 0 or more batch dimensions. 63 | 64 | :param deg: int SH max degree. Currently, 0-4 supported 65 | :param sh: torch.Tensor SH coeffs (..., C, (max degree + 1) ** 2) 66 | :param dirs: torch.Tensor unit directions (..., 3) 67 | 68 | :return: (..., C) 69 | """ 70 | assert deg <= 4 and deg >= 0 71 | assert (deg + 1) ** 2 == sh.shape[-1] 72 | C = sh.shape[-2] 73 | 74 | result = C0 * sh[..., 0] 75 | if deg > 0: 76 | x, y, z = dirs[..., 0:1], dirs[..., 1:2], dirs[..., 2:3] 77 | result = (result - 78 | C1 * y * sh[..., 1] + 79 | C1 * z * sh[..., 2] - 80 | C1 * x * sh[..., 3]) 81 | if deg > 1: 82 | xx, yy, zz = x * x, y * y, z * z 83 | xy, yz, xz = x * y, y * z, x * z 84 | result = (result + 85 | C2[0] * xy * sh[..., 4] + 86 | C2[1] * yz * sh[..., 5] + 87 | C2[2] * (2.0 * zz - xx - yy) * sh[..., 6] + 88 | C2[3] * xz * sh[..., 7] + 89 | C2[4] * (xx - yy) * sh[..., 8]) 90 | 91 | if deg > 2: 92 | result = (result + 93 | C3[0] * y * (3 * xx - yy) * sh[..., 9] + 94 | C3[1] * xy * z * sh[..., 10] + 95 | C3[2] * y * (4 * zz - xx - yy)* sh[..., 11] + 96 | C3[3] * z * (2 * zz - 3 * xx - 3 * yy) * sh[..., 12] + 97 | C3[4] * x * (4 * zz - xx - yy) * sh[..., 13] + 98 | C3[5] * z * (xx - yy) * sh[..., 14] + 99 | C3[6] * x * (xx - 3 * yy) * sh[..., 15]) 100 | if deg > 3: 101 | result = (result + C4[0] * xy * (xx - yy) * sh[..., 16] + 102 | C4[1] * yz * (3 * xx - yy) * sh[..., 17] + 103 | C4[2] * xy * (7 * zz - 1) * sh[..., 18] + 104 | C4[3] * yz * (7 * zz - 3) * sh[..., 19] + 105 | C4[4] * (zz * (35 * zz - 30) + 3) * sh[..., 20] + 106 | C4[5] * xz * (7 * zz - 3) * sh[..., 21] + 107 | C4[6] * (xx - yy) * (7 * zz - 1) * sh[..., 22] + 108 | C4[7] * xz * (xx - 3 * yy) * sh[..., 23] + 109 | C4[8] * (xx * (xx - 3 * yy) - yy * (3 * xx - yy)) * sh[..., 24]) 110 | return result 111 | 112 | 113 | def eval_sh_bases(deg, dirs): 114 | """ 115 | Evaluate spherical harmonics bases at unit directions, 116 | without taking linear combination. 117 | At each point, the final result may the be 118 | obtained through simple multiplication. 119 | 120 | :param deg: int SH max degree. Currently, 0-4 supported 121 | :param dirs: torch.Tensor (..., 3) unit directions 122 | 123 | :return: torch.Tensor (..., (deg+1) ** 2) 124 | """ 125 | assert deg <= 4 and deg >= 0 126 | result = torch.empty((*dirs.shape[:-1], (deg + 1) ** 2), dtype=dirs.dtype, device=dirs.device) 127 | result[..., 0] = C0 128 | if deg > 0: 129 | x, y, z = dirs.unbind(-1) 130 | result[..., 1] = -C1 * y; 131 | result[..., 2] = C1 * z; 132 | result[..., 3] = -C1 * x; 133 | if deg > 1: 134 | xx, yy, zz = x * x, y * y, z * z 135 | xy, yz, xz = x * y, y * z, x * z 136 | result[..., 4] = C2[0] * xy; 137 | result[..., 5] = C2[1] * yz; 138 | result[..., 6] = C2[2] * (2.0 * zz - xx - yy); 139 | result[..., 7] = C2[3] * xz; 140 | result[..., 8] = C2[4] * (xx - yy); 141 | 142 | if deg > 2: 143 | result[..., 9] = C3[0] * y * (3 * xx - yy); 144 | result[..., 10] = C3[1] * xy * z; 145 | result[..., 11] = C3[2] * y * (4 * zz - xx - yy); 146 | result[..., 12] = C3[3] * z * (2 * zz - 3 * xx - 3 * yy); 147 | result[..., 13] = C3[4] * x * (4 * zz - xx - yy); 148 | result[..., 14] = C3[5] * z * (xx - yy); 149 | result[..., 15] = C3[6] * x * (xx - 3 * yy); 150 | 151 | if deg > 3: 152 | result[..., 16] = C4[0] * xy * (xx - yy); 153 | result[..., 17] = C4[1] * yz * (3 * xx - yy); 154 | result[..., 18] = C4[2] * xy * (7 * zz - 1); 155 | result[..., 19] = C4[3] * yz * (7 * zz - 3); 156 | result[..., 20] = C4[4] * (zz * (35 * zz - 30) + 3); 157 | result[..., 21] = C4[5] * xz * (7 * zz - 3); 158 | result[..., 22] = C4[6] * (xx - yy) * (7 * zz - 1); 159 | result[..., 23] = C4[7] * xz * (xx - 3 * yy); 160 | result[..., 24] = C4[8] * (xx * (xx - 3 * yy) - yy * (3 * xx - yy)); 161 | return result 162 | -------------------------------------------------------------------------------- /svox/csrc/svox_kernel.cu: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 PlenOctree Authors 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | #include "common.cuh" 29 | #include "data_spec_packed.cuh" 30 | 31 | #define CUDA_N_THREADS 1024 32 | 33 | namespace { 34 | void check_indices(torch::Tensor& indices) { 35 | CHECK_INPUT(indices); 36 | TORCH_CHECK(indices.dim() == 2); 37 | TORCH_CHECK(indices.is_floating_point()); 38 | } 39 | 40 | namespace device { 41 | 42 | template 43 | __device__ __inline__ scalar_t* get_tree_leaf_ptr( 44 | torch::PackedTensorAccessor64 45 | data, 46 | PackedTreeSpec& __restrict__ tree, 47 | const scalar_t* __restrict__ xyz_ind, 48 | int64_t* node_id=nullptr) { 49 | scalar_t xyz[3] = {xyz_ind[0], xyz_ind[1], xyz_ind[2]}; 50 | transform_coord(xyz, tree.offset, tree.scaling); 51 | scalar_t _cube_sz; 52 | return query_single_from_root(data, tree.child, 53 | xyz, &_cube_sz, node_id); 54 | } 55 | 56 | template 57 | __global__ void query_single_kernel( 58 | PackedTreeSpec tree, 59 | const torch::PackedTensorAccessor32 indices, 60 | torch::PackedTensorAccessor64 values_out, 61 | torch::PackedTensorAccessor32 node_ids_out) { 62 | CUDA_GET_THREAD_ID(tid, indices.size(0)); 63 | scalar_t* data_ptr = get_tree_leaf_ptr(tree.data, tree, &indices[tid][0], &node_ids_out[tid]); 64 | for (int i = 0; i < tree.data.size(4); ++i) 65 | values_out[tid][i] = data_ptr[i]; 66 | } 67 | 68 | template 69 | __global__ void query_single_kernel_backward( 70 | PackedTreeSpec tree, 71 | const torch::PackedTensorAccessor32 indices, 72 | const torch::PackedTensorAccessor64 grad_output, 73 | torch::PackedTensorAccessor64 grad_data_out) { 74 | CUDA_GET_THREAD_ID(tid, indices.size(0)); 75 | scalar_t* data_ptr = get_tree_leaf_ptr(grad_data_out, tree, &indices[tid][0]); 76 | for (int i = 0; i < grad_output.size(1); ++i) 77 | atomicAdd(&data_ptr[i], grad_output[tid][i]); 78 | } 79 | 80 | template 81 | __global__ void assign_single_kernel( 82 | PackedTreeSpec tree, 83 | const torch::PackedTensorAccessor32 indices, 84 | const torch::PackedTensorAccessor64 values) { 85 | CUDA_GET_THREAD_ID(tid, indices.size(0)); 86 | scalar_t* data_ptr = get_tree_leaf_ptr(tree.data, tree, &indices[tid][0]); 87 | for (int i = 0; i < values.size(1); ++i) 88 | data_ptr[i] = values[tid][i]; 89 | } 90 | 91 | template 92 | __global__ void calc_corner_kernel( 93 | PackedTreeSpec tree, 94 | const torch::PackedTensorAccessor32 indexer, 95 | torch::PackedTensorAccessor32 output) { 96 | CUDA_GET_THREAD_ID(tid, indexer.size(0)); 97 | const int N = tree.data.size(1); 98 | const auto* leaf = &indexer[tid][0]; 99 | scalar_t* result = &output[tid][0]; 100 | 101 | int32_t curr[4] = {(int32_t) leaf[0], (int32_t) leaf[1], 102 | (int32_t) leaf[2], (int32_t) leaf[3]}; 103 | while (true) { 104 | for (int i = 0; i < 3; ++i) { 105 | result[i] += curr[i + 1]; 106 | result[i] /= N; 107 | } 108 | if (curr[0] == 0) break; 109 | curr[0] = tree.parent_depth[curr[0]][0]; 110 | for (int i = 3; i > 0; --i) { 111 | curr[i] = curr[0] % N; 112 | curr[0] /= N; 113 | } 114 | } 115 | } 116 | 117 | } // namespace device 118 | } // namespace 119 | 120 | QueryResult query_vertical(TreeSpec& tree, torch::Tensor indices) { 121 | tree.check(); 122 | check_indices(indices); 123 | DEVICE_GUARD(indices); 124 | 125 | const auto Q = indices.size(0), K = tree.data.size(4); 126 | 127 | const int blocks = CUDA_N_BLOCKS_NEEDED(Q, CUDA_N_THREADS); 128 | torch::Tensor values = torch::empty({Q, K}, indices.options()); 129 | auto node_ids_options = at::TensorOptions() 130 | .dtype(at::kLong) 131 | .layout(tree.child.layout()) 132 | .device(tree.child.device()); 133 | torch::Tensor node_ids = torch::empty({Q}, node_ids_options); 134 | AT_DISPATCH_FLOATING_TYPES(indices.type(), __FUNCTION__, [&] { 135 | device::query_single_kernel<<>>( 136 | tree, 137 | indices.packed_accessor32(), 138 | values.packed_accessor64(), 139 | node_ids.packed_accessor32()); 140 | }); 141 | CUDA_CHECK_ERRORS; 142 | return QueryResult(values, node_ids); 143 | } 144 | 145 | void assign_vertical(TreeSpec& tree, torch::Tensor indices, torch::Tensor values) { 146 | tree.check(); 147 | check_indices(indices); 148 | check_indices(values); 149 | DEVICE_GUARD(indices); 150 | const int blocks = CUDA_N_BLOCKS_NEEDED(indices.size(0), CUDA_N_THREADS); 151 | AT_DISPATCH_FLOATING_TYPES(indices.type(), __FUNCTION__, [&] { 152 | device::assign_single_kernel<<>>( 153 | tree, 154 | indices.packed_accessor32(), 155 | values.packed_accessor64()); 156 | }); 157 | CUDA_CHECK_ERRORS; 158 | } 159 | 160 | torch::Tensor query_vertical_backward( 161 | TreeSpec& tree, 162 | torch::Tensor indices, 163 | torch::Tensor grad_output) { 164 | tree.check(); 165 | DEVICE_GUARD(indices); 166 | const auto Q = indices.size(0), N = tree.child.size(1), 167 | K = grad_output.size(1), M = tree.child.size(0); 168 | const int blocks = CUDA_N_BLOCKS_NEEDED(Q, CUDA_N_THREADS); 169 | 170 | torch::Tensor grad_data = torch::zeros({M, N, N, N, K}, grad_output.options()); 171 | 172 | AT_DISPATCH_FLOATING_TYPES(indices.type(), __FUNCTION__, [&] { 173 | device::query_single_kernel_backward<<>>( 174 | tree, 175 | indices.packed_accessor32(), 176 | grad_output.packed_accessor64(), 177 | grad_data.packed_accessor64()); 178 | }); 179 | 180 | CUDA_CHECK_ERRORS; 181 | return grad_data; 182 | } 183 | 184 | torch::Tensor calc_corners( 185 | TreeSpec& tree, 186 | torch::Tensor indexer) { 187 | tree.check(); 188 | DEVICE_GUARD(indexer); 189 | const auto Q = indexer.size(0); 190 | const int blocks = CUDA_N_BLOCKS_NEEDED(Q, CUDA_N_THREADS); 191 | 192 | torch::Tensor output = torch::zeros({Q, 3}, tree.data.options()); 193 | 194 | AT_DISPATCH_FLOATING_TYPES(tree.data.type(), __FUNCTION__, [&] { 195 | device::calc_corner_kernel<<>>( 196 | tree, 197 | indexer.packed_accessor32(), 198 | output.packed_accessor32()); 199 | }); 200 | 201 | CUDA_CHECK_ERRORS; 202 | return output; 203 | } 204 | -------------------------------------------------------------------------------- /docs/build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["ex_nerf","ex_opt_toy","index","quick","svox"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["ex_nerf.rst","ex_opt_toy.rst","index.rst","quick.rst","svox.rst"],objects:{"svox.N3Tree":{__init__:[4,1,1,""],accumulate_weights:[4,1,1,""],check_integrity:[4,1,1,""],clone:[4,1,1,""],diam_frontier:[4,1,1,""],expand:[4,1,1,""],forward:[4,1,1,""],from_grid:[4,1,1,""],frontier_depth:[4,1,1,""],load:[4,1,1,""],max_depth:[4,1,1,""],max_frontier:[4,1,1,""],merge:[4,1,1,""],n_frontier:[4,1,1,""],partial:[4,1,1,""],reduce_frontier:[4,1,1,""],refine:[4,1,1,""],save:[4,1,1,""],set:[4,1,1,""],set_grid:[4,1,1,""],shrink:[4,1,1,""],shrink_to_fit:[4,1,1,""],snap:[4,1,1,""],tree2world:[4,1,1,""],world2tree:[4,1,1,""]},"svox.N3TreeView":{__init__:[4,1,1,""],aux:[4,1,1,""],clamp_:[4,1,1,""],corners:[4,1,1,""],corners_local:[4,1,1,""],depths:[4,1,1,""],lengths:[4,1,1,""],lengths_local:[4,1,1,""],nan_to_num_:[4,1,1,""],normal_:[4,1,1,""],refine:[4,1,1,""],relu_:[4,1,1,""],sample:[4,1,1,""],sample_local:[4,1,1,""],sigmoid_:[4,1,1,""],uniform_:[4,1,1,""],values:[4,1,1,""],values_nograd:[4,1,1,""]},"svox.VolumeRenderer":{__init__:[4,1,1,""],forward:[4,1,1,""],persp_rays:[4,1,1,""],render_persp:[4,1,1,""],se_grad:[4,1,1,""],se_grad_persp:[4,1,1,""]},svox:{N3Tree:[4,0,1,""],N3TreeView:[4,0,1,""],VolumeRenderer:[4,0,1,""]}},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"]},objtypes:{"0":"py:class","1":"py:method"},terms:{"001":4,"1024":4,"111":[0,4],"1111":[0,4],"14024":2,"1e2":1,"1xri_yqdcdrfwqoqv3qpoeozynuhagi5m":0,"20000":4,"2043267":1,"2103":2,"21440998":1,"22599061":1,"23945224":1,"25531954":1,"27432522":1,"29751268":1,"32639033":1,"3631369":1,"4107593":1,"42875046":1,"4483344":1,"46970066":1,"49309036":1,"49648416":1,"4977861":1,"4995423":1,"50186735":1,"50490075":1,"5088086":1,"51378375":1,"5188446":1,"52003586":1,"5277597":1,"5370555":1,"54321104":1,"5475207":1,"5502867":1,"55849427":1,"5681365":1,"579674":1,"58019906":1,"59386927":1,"61214054":1,"6194525":1,"63762873":1,"6409838":1,"6420485":1,"64437073":1,"64582":1,"6513118":1,"65586865":1,"657904":1,"66518104":1,"6728529":1,"67369866":1,"6790305972099304":0,"6790306568145752":0,"67984015":1,"6859846":1,"71049845":1,"7341098785400391":0,"7341099977493286":0,"737260103225708":0,"7405325":1,"7646569":1,"7842779":1,"800":[0,4],"80046684":1,"8140159":1,"8255081":1,"83537465":1,"84393847":1,"88920575":1,"959291696548462":0,"9999999403953552":0,"break":4,"case":3,"class":[3,4],"default":[3,4],"final":3,"float":[3,4],"function":[1,3,4],"import":[0,1,2,3],"int":[3,4],"new":4,"return":[3,4],"static":4,"switch":1,"true":[1,3,4],"try":4,"var":4,"while":3,For:[3,4],NOT:4,The:[1,2,3,4],Then:1,These:3,Use:4,Will:4,__init__:4,_local:3,aabb:4,about:3,abs:[2,3],acceler:[2,4],accessor:2,accoord:4,accord:4,accum:[3,4],accumul:[2,4],accumulate_weight:[3,4],accur:4,accuraci:4,actual:4,added:4,advanc:2,after:[3,4],alex:2,alexyu:2,algorithm:4,alia:4,all:[3,4],allow:3,almost:4,also:3,although:4,alwai:[3,4],amount:4,analog:3,analyt:3,angjoo:2,ani:[3,4],anisotrop:3,appli:4,appropri:1,approxim:3,arbitrari:4,arg:4,argmax:4,argument:[3,4],arr:4,arrai:4,arxiv:2,asg:[3,4],associ:4,assum:4,autograd:4,automat:[1,3,4],aux:4,auxiliari:4,avail:[2,4],availbl:[],avoid:4,axi:3,back:3,background:4,background_bright:4,backward:[1,3],base:4,basi:[3,4],basis_dim:[3,4],batch:[3,4],becaus:4,been:4,befor:4,begin:[3,4],behav:3,being:3,below:3,bewar:[],bit:3,bool:4,both:4,bound:3,boundari:4,branch:4,branch_factor:[],bright:4,buffer:4,bug:4,build:3,built:[3,4],bulldoz:2,c2w:[0,4],call:4,camera:[3,4],can:[0,3,4],cannot:[3,4],capabl:3,capac:[2,4],cat:4,caus:4,center:[3,4],chang:4,channel:[1,4],check:[3,4],check_integr:4,checkpoint:3,child:4,children:4,clamp:4,clamp_:[0,3,4],classmethod:4,clip:3,clone:4,closer:1,code:[2,3,4],color:[1,3,4],com:[0,2],combin:4,come:4,compat:4,compil:3,complet:3,compon:4,compress:4,comput:4,condit:4,configur:4,confus:3,constant:4,construct:[2,4],constructor:3,contain:4,context:2,contigu:3,continu:1,conveni:3,convert:[3,4],coordin:[3,4],copi:[0,4],core:3,corner:[3,4],corners_loc:4,correct:4,correspond:[3,4],cost:3,could:[3,4],cours:3,cpu:[0,1,3,4],creat:4,cube:[3,4],cuda:[0,1,2,3,4],current:[3,4],data:[1,2,4],data_dim:[2,3,4],data_format:[1,3,4],data_sel:4,dataformat:4,dda:[],deal:4,debug:4,dedup:4,deep:4,def:4,delta_i:3,delta_j:3,densiti:[3,4],density_softplu:4,deprec:4,depth:[3,4],depth_limit:[2,3,4],deriv:3,desc:1,descent:1,detach:1,detail:[2,3],detect:4,determin:[3,4],dev:2,devic:[0,1,3,4],diag_hessian:4,diagon:4,diam_fronti:4,diamet:4,differenti:2,dim:4,dimens:[3,4],dimension:3,dir:[1,3,4],direct:3,directli:3,disabl:4,discard:4,document:3,doe:[2,4],don:4,download:0,drive:0,dtype:4,due:4,duplic:4,each:[2,3,4],earli:3,edg:3,effect:4,effici:[3,4],either:3,element:4,els:4,emit:3,empti:4,enabl:4,entir:4,entri:3,eps:4,equal:[3,4],error:[3,4],etc:4,evalu:4,even:4,everi:3,exampl:[2,3,4],exp:[3,4],expand:[2,4],explicitli:3,extens:[2,3],extra:[1,4],extra_data:[3,4],factor:4,fail:[3,4],fals:4,familiar:4,fast:[3,4],faster:4,featur:[2,3],field:[2,3],file:[0,3,4],first:[3,4],fit:4,fix:1,fixm:4,float32:4,float64:4,focal:[3,4],follow:3,format:[1,3,4],formula:3,forward:[3,4],frac:4,fragment:4,freed:4,from:[0,3,4],from_grid:4,frontier:4,frontier_depth:4,frontier_sel:4,gauss:4,gaussian:3,gener:[2,4],geom_resize_fact:4,geometr:4,get:[1,3,4],github:2,give:3,given:4,googl:0,grab:3,grad:[1,3,4],gradient:[1,4],grai:4,greater:4,grid:4,guid:2,half:3,hao:2,harmon:3,has:[3,4],hat:4,have:[3,4],heigh:3,height:[0,3,4],help:[3,4],here:[3,4],hessian:4,hit:3,how:3,http:[0,2],iff:4,im_gt:3,imag:[0,3,4],implement:[2,3,4],imshow:0,in_dim:4,includ:4,incompat:3,index:[3,4],indic:[3,4],ineffici:[3,4],inf:4,inf_val:4,infer:4,influenc:3,infti:3,init:4,init_refin:[3,4],init_reserv:4,initi:[3,4],insert:1,instal:[2,3],instanc:4,instead:4,int32:4,integr:4,interior:4,intern:3,interpol:4,intersect:4,interv:4,invalid:4,involv:2,item:3,jacobian:4,kanazawa:2,kei:4,kernel:4,kwarg:4,larger:4,last:[3,4],lead:4,leaf:[2,4],leav:[3,4],left:3,lego:2,lego_sm:[],length:[3,4],lengths_loc:4,less:4,level:2,librari:[3,4],like:[3,4],limit:3,list:[3,4],load:[0,2,4],local:[3,4],lod:3,log:4,loss:4,lower:4,lowest:[3,4],luminos:4,mai:[3,4],major:4,make:[3,4],manag:3,manipul:3,manual:1,map:4,map_loc:4,mask:4,mathbf:3,mathcal:4,matplotlib:0,matrix:[0,3,4],matthew:2,max:[3,4],max_comp:4,max_depth:[2,4],max_fronti:4,maximum:[3,4],mean:[3,4],mean_and_var_func:4,memori:4,merg:4,messag:4,method:[2,3,4],middl:1,min:4,min_comp:4,mind:4,minimum:4,mip:4,model:0,modifi:[2,4],modul:[3,4],more:[2,3],most:[3,4],mostli:4,mse:1,much:3,multipl:4,must:3,n3tree:[0,1,2,3,4],n3treeview:[2,4],n_frontier:4,n_leav:[3,4],n_sampl:[3,4],name:4,namedtupl:4,nan:4,nan_to_num_:4,ndc:[3,4],ndcconfig:[3,4],need:[3,4],neg:3,nerf:[2,3,4],net:2,network:2,neural:2,new_data:4,newton:4,nnl:4,no_grad:0,node:[3,4],non:3,none:[3,4],norm:4,normal:4,normal_:[3,4],note:[2,3,4],noth:4,now:4,npz:[0,3,4],npz_path:3,number:[3,4],numpi:1,nxnxn:3,object:4,octre:[1,2,3,4],old:4,old_data:4,onc:3,one:3,onli:[2,3,4],oper:[2,3,4],optim:[2,3,4],option:[3,4],oracl:2,order:[3,4],org:2,origin:[1,3,4],other:[3,4],output:[1,3,4],over:4,overrid:4,oversatur:4,overview:[2,3],pad:4,paper:2,param:4,paramet:[3,4],part:[2,4],partial:4,particular:4,pass:[3,4],path:4,per:[2,3],perform:4,persist:4,persp_rai:4,perspect:[3,4],pip:[2,3],pleas:[2,3,4],plenoctre:[0,2],plt:0,point:[3,4],pose:[3,4],posit:4,possibl:4,potenti:[3,4],pre:[3,4],print:[1,2,3],process:3,prod_:3,product:[],project:2,properli:3,properti:4,provid:[3,4],put:[3,4],pyplot:0,pytorch:[2,3,4],qualiti:3,queri:[2,4],quick:2,radianc:2,radiu:[3,4],rai:[1,3,4],random:[3,4],rang:1,ray_dir:1,ray_ori:1,real:[2,3],reason:4,recov:4,reduc:4,reduce_fronti:4,reduct:4,redund:3,refer:[2,3],refin:[2,4],reiniti:4,relat:2,releas:2,relu:4,relu_:4,remap:4,ren:[2,3],rend:1,render:2,render_persp:[0,3,4],repeat:4,repo:2,requir:[3,4],reserv:4,resiz:4,reslut:4,resolut:4,respect:[3,4],rest:4,result:[1,4],rgb:1,rgb_dim:4,rgb_pad:4,rgba:[3,4],right:[3,4],root:[3,4],row:4,ruilong:2,runtim:3,same:[3,4],sampl:[3,4],sample_loc:4,save:[2,4],scale:4,se_grad:4,se_grad_persp:4,section:3,see:[2,3,4],segment:3,sel:4,select:4,selector:4,self:[3,4],set:[0,4],set_grid:4,sh1:1,sh4:1,shape:[3,4],share:0,shift:4,should:[3,4],show:0,shrank:3,shrink:4,shrink_to_fit:4,side:[3,4],sigma:[3,4],sigma_i:3,sigma_j:3,sigmoid:4,sigmoid_:4,signatur:4,similar:3,similarli:3,simpli:[3,4],sinc:3,size:[2,3,4],slow:[3,4],slowli:1,small:4,smaller:4,snap:4,softplu:4,some:[3,4],someth:3,sometim:3,somewhat:3,sourc:2,space:[3,4],spatial:3,specifi:[3,4],spheric:3,squar:[3,4],start:[1,3],std:4,step:4,step_siz:4,still:4,stop:[3,4],store:[0,2,3,4],str:4,string:[3,4],structur:4,sum:[1,3,4],sum_:[3,4],support:[3,4],sure:3,svox:[0,1,3,4],sxox:3,sxyu:2,system:3,take:[3,4],taken:[],tancik:2,target:1,tensor:[0,1,3,4],test:0,than:[3,4],them:[3,4],thi:[0,1,2,3,4],through:3,thrown:3,tightli:4,time:[2,3,4],tini:1,tip:4,torch:[0,1,3,4],total:[3,4],trace:4,train:2,transform:3,tree2world:4,tree:[2,3],troubleshoot:3,tupl:4,twice:3,type:4,typic:[3,4],uniform:4,uniform_:4,uniformli:3,uniqu:4,unless:4,updat:3,usabl:4,use:[3,4],used:[3,4],useful:4,uses:4,using:[0,1,2,4],usp:0,usual:[3,4],util:3,valid:4,valu:[3,4],values_nograd:4,varianc:[3,4],vector:1,veri:[3,4],verifi:4,version:[2,3,4],view:[0,2,3],viewdir:[1,3,4],volrend:4,volum:2,volumerender:[0,1,3,4],voxel:[3,4],wai:4,want:3,want_node_id:4,warn:[3,4],wast:4,websit:2,weight:[2,4],when:3,where:[3,4],whether:4,which:[1,3,4],white:4,width:[0,3,4],wish:3,within:[3,4],without:3,work:3,world2tre:4,world:4,worri:4,would:3,wrt:[3,4],you:[0,3,4],your:3,your_out_dim:4,zero_grad:1},titles:["Example: Lego Bulldozer Rendering","Example: Optimization and expand","Welcome to the svox documentation","Quick Guide","Reference"],titleterms:{accessor:3,accumul:3,advanc:3,bulldoz:0,construct:3,content:2,context:3,data:3,differenti:[3,4],document:2,exampl:[0,1],expand:1,guid:3,leaf:3,lego:0,level:3,load:3,modifi:3,n3treeview:3,optim:1,oracl:3,queri:3,quick:3,refer:4,refin:3,render:[0,3,4],save:3,svox:2,tree:4,using:3,view:4,volum:[3,4],weight:3,welcom:2}}) -------------------------------------------------------------------------------- /docs/source/quick.rst: -------------------------------------------------------------------------------- 1 | .. _quick: 2 | 3 | Quick Guide 4 | ================== 5 | 6 | Below I give a quick overview of some core functionality of svox to help get you started. 7 | Please see :ref:`svox` for detailed per-method documentation. 8 | To install the library, simply use :code:`pip install sxox`; you would of course need 9 | to install PyTorch first. 10 | You will also need the CUDA runtime to compile the CUDA extension; 11 | while the library works without the CUDA extension, it is very slow, and will emit a warning the 12 | first time a CUDA-capable operation is used. 13 | 14 | If the extension fails to build, check if your PyTorch is using the same CUDA 15 | version as you have installed on your system. 16 | 17 | Construction 18 | ------------------------------- 19 | 20 | We begin by importing the library and constructing a tree: 21 | 22 | >>> import svox 23 | >>> t=svox.N3Tree(data_dim=4, data_format="RGBA", 24 | center=[0.5, 0.5, 0.5], radius=0.5, 25 | N=2, device="cpu", 26 | init_refine=0, depth_limit=10, 27 | extra_data=None) 28 | >>> t.cuda() 29 | 30 | * :code:`data_dim` is the size of data to store in each leaf, for example 4 for :code:`RGBA` data. 31 | Since 0.2.28: this is optional if :code:`data_format` is something other than :code:`RGBA`. 32 | Since 0.2.27: an error is thrown if this is incompatible with :code:`data_format`. 33 | * :code:`data_format`, a bit redundant, is the data format for rendering (only used for VolumeRenderer). 34 | It can be :code:`RGBA`, :code:`SH#`, :code:`SG#`, or :code:`ASG#`, where # (basis_dim) is the dimensionality of the basis function. 35 | This is somewhat redundant with data_dim. 36 | data_dim should be :code:`basis_dim * 3 + 1` (Last item is always :math:`\sigma \in [0, \infty)`, the density). 37 | For SH (spherical harmonics), basis_dim must be a square number at most 25. SG (spherical Gaussians) and ASG (anisotropic SG) require :code:`extra_data` field to render properly. 38 | * :code:`radius` and :code:`center` specify the transform of the tree in space, with :code:`radius` meaning the half-edge length of the bounding cube (1 float or list of 3 floats for each axis) and :code:`center` specifying the center of the cube (list of 3 floats). By default cube is centered at :code:`[0.5, 0.5, 0.5]` with radius 0.5. 39 | * :code:`N` (optional, default 2) is the N in :math:`N^3` tree. Typically, put :code:`N=2` for an octree. 40 | * :code:`device` (optional, default cpu) can be a string like 'cuda' and is where the tree's data will be stored. 41 | * :code:`init_refine` specifies initial LOD of the tree: the initial leaf voxel size will be :code:`N^(init_refine + 1)`. 42 | * :code:`depth_limit` is a utility for limiting the maximum depth of any tree leaf after refinement. Note that the root is at depth -1, which may be a bit confusing; initially the tree has maximum depth 1 and :code:`NxNxN` leaves. 43 | * :code:`extra_data` for SG, basis_dim x 4 matrix of variance/mean (3). For ASG, data_dim x 11 matrix. 44 | Currently, optimizing wrt this matrix is not supported, so the parameters should be pre-determined. 45 | 46 | :code:`svox.N3Tree` is a PyTorch module and 47 | usual operations such as :code:`.parameters()` or :code:`.cuda()` can be used. 48 | The forward method of the N3Tree class takes a batch of points :code:`(B, 3)` and returns 49 | corresponding data. 50 | 51 | Saving and Loading 52 | ------------------------------ 53 | To save and load trees to/from npz files, use 54 | 55 | >>> tree.save(npz_path) 56 | >>> tree = svox.N3Tree.load(npz_path, device=device) 57 | 58 | 'device' can be a string like 'cuda' and is where the tree's data will be loaded into, similar 59 | to that in the constructor. 60 | Since the tree is a PyTorch module, you could also use a PyTorch checkpoint, but it can be VERY inefficient. 61 | 62 | Querying and Modifying Data using N3TreeView 63 | --------------------------------------------- 64 | 65 | For convenient query and manipulation, we provide an approximate analogy to the PyTorch tensor, 66 | where the tree is viewed as a matrix of size 67 | :code:`(n_leaves, data_dim)`. Any indexing operation into the N3Tree returns a 68 | :code:`N3TreeView` class which works like a tensor. 69 | 70 | >>> tree.shape 71 | torch.Size([8, 4]) 72 | >>> tree[0] += 1 73 | >>> tree[:, :3] 74 | N3TreeView(tensor([[1., 1., 1.], 75 | [0., 0., 0.], 76 | [0., 0., 0.], 77 | [0., 0., 0.], 78 | [0., 0., 0.], 79 | [0., 0., 0.], 80 | [0., 0., 0.], 81 | [0., 0., 0.]])) 82 | >>> tree[:, -1:] = -1 83 | >>> tree[:2] 84 | N3TreeView(tensor([[ 1., 1., 1., -1.], 85 | [ 0., 0., 0., -1.]])) 86 | 87 | You can also, of course, query the tree using *real spatial points*, 88 | by either using 3 indices or a :code:`(N, 3)` query matrix: 89 | 90 | >>> tree[0, 0.5, 0] # Query point (0, 0.5, 0) 91 | >>> tree[points] # Query points (N, 3) 92 | 93 | This returns a N3TreeView of leaves corresponding to these points, so you can also modify them: 94 | 95 | >>> tree[points] = values # Query points (N, 3), values (N, data_dim) 96 | >>> tree[0, 0, 0] /= 2.0 97 | 98 | The tree is self behaves similarly to :code:`tree[:]`. Some more examples: 99 | 100 | >>> tree += 1.5 101 | >>> tree.normal_() 102 | >>> tree[:, -1:].clamp_(0.1, None) 103 | 104 | When used with a PyTorch operation such as :code:`torch.mean` or operators like :code:`+`, 105 | the N3TreeView is queried and the values are converted to a PyTorch tensor automatically. 106 | If you wish to get the values as a tensor explicitly, use :code:`view.values`. 107 | See the section :ref:`Advanced Leaf-level Accessors` for more advanced operations supported by 108 | N3TreeView. 109 | 110 | Refinement oracle 111 | --------------------- 112 | 113 | To refine the tree, use the :code:`refine` function. 114 | The first argument allows you to refine more than once. 115 | 116 | >>> tree.refine() # Refine all nodes 117 | >>> tree.refine(2) # Refine all nodes twice 118 | >>> tree[-1].refine() # Refine leaf -1 once, through the N3TreeView 119 | 120 | Differentiable Volume Rendering 121 | --------------------------------- 122 | This is implemented in the :code:`svox.VolumeRenderer` class. 123 | The following code renders a perspective image: 124 | 125 | >>> ren = svox.VolumeRenderer(tree) 126 | >>> camera = # some [4, 4] camera pose matrix 127 | >>> ren.render_persp(camera, width=width, height=height, fx=fx) # Get a perspective image 128 | 129 | Note the renderer need not be updated if the tree is modified. 130 | The renderer will use the tree's :code:`data_format` field: 131 | one of :code:`RGBA`, :code:`SH#`, :code:`SG#`, or :code:`ASG#`, where # (basis_dim) is the dimensionality of the basis function. 132 | For SH, this must be a square number at most 25. 133 | The last dimension is always used as density :math:`\sigma \in [0, \infty)`, where the value is clipped to 0 while rendering if negative. 134 | The volume rendering formula is as in NeRF: 135 | 136 | .. math:: 137 | \mathbf{C} = \sum_{i=1}^n \left[\prod_{j=1}^{i-1}\exp(-\delta_j \sigma_j)\right] \left[1 - \exp(-\delta_i \sigma_i)\right] \mathbf{c}_i(\mathbf{d}) 138 | 139 | Where :math:`\delta_i, \sigma_i, \mathbf{c}_i` are segment i's length, density, and color, respectively. :math:`\mathbf{d}` is the viewing direction 140 | and :math:`\mathbf{C}` is the final output color. 141 | 142 | Also you can render rays directly, by using the forward method of VolumeRenderer: 143 | 144 | >>> ray = svox.Rays(origins = ... dirs=..., viewdirs=...) 145 | >>> ren(ray) 146 | 147 | You can pass :code:`fast=True` to either render_persp or this forward method 148 | to allow fast rendering (with early stopping) potentially at the cost of quality. 149 | 150 | These functions are backed by CUDA analytic derivatives. 151 | For example, 152 | 153 | >>> im = ren.render_persp(camera) 154 | >>> torch.abs(im - im_gt).mean().backward() 155 | >>> print(tree.data.grad.shape) 156 | 157 | Finally, NDC views are also internally supported in render_persp. 158 | To use this features, pass :code:`ndc=svox.NDCConfig(width=..., heigh=..., focal=...)` 159 | to the VolumeRenderer constructor. 160 | 161 | **Troubleshooting**: If you get an error about a tensor being non-contiguous, 162 | please make sure it is contiguous using 163 | :code:`.contiguous()`, for example 164 | :code:`svox.Rays(origins=r[:, :3].contiguous(), dirs=r[:, 3:6].contiguous(), viewdirs=r[:, 3:6].contiguous())`. 165 | 166 | .. _leaf_level_acc: 167 | 168 | Advanced Leaf-level Accessors 169 | ------------------------------ 170 | Some more functions for working with leaves 171 | 172 | >>> tree.lengths # Side lengths of each leaf voxel (same order as leaf matrix) 173 | >>> tree.depths # Depth of each leaf voxel (root is at **-1**) 174 | >>> tree.corners # Lowest corner of each leaf voxel 175 | >>> tree.values # Values at each leaf voxel 176 | >>> tree.sample(n_samples: int) # Sample uniformly random points in each voxel 177 | 178 | In each case you may also use N3TreeView, for example 179 | 180 | >>> tree[tree.depths==2].corners 181 | 182 | For each of lengths/corners/sample there is also a \*_local version 183 | which returns points and lengths in local coordinates :math:`[0,1]^3`. 184 | 185 | Advanced: Volume Rendering Weight Accumulator Context 186 | ------------------------------------------------------- 187 | Sometimes we want to accumulate volume rendering weights in each tree leaf, 188 | to see how much each leaf voxel was used in the rendering process. 189 | We may either want the max or total rendering weight (influence) within each voxel. 190 | We have a built-in context manager to do so. 191 | 192 | >>> with tree.accumulate_weights(op="sum") as accum: # or op="max" 193 | >>> # Do some ray/image rendering with a renderer on the tree 194 | >>> # Tree cannot be refined or shrank here 195 | >>> accum = accum() 196 | 197 | The final :code:`accum` is a float tensor of shape 198 | equal to tree.n_leaves which can 199 | be used to index into the tree. 200 | Each entry is equal to the *sum* of all volume rendering *weights* 201 | for all rays which every hit the voxel within the context. 202 | You can use it as follows: 203 | 204 | >>> tree[accum > 1.0].refine() 205 | >>> tree[accum < 1.0] += 1 206 | 207 | *Advanced*: You can also use :code:`accum.value` to grab the complete 208 | accumulated tensor of size equal to :code:`tree.data`. 209 | This is more efficient than using :code:`accum()`. 210 | -------------------------------------------------------------------------------- /docs/build/html/_sources/quick.rst.txt: -------------------------------------------------------------------------------- 1 | .. _quick: 2 | 3 | Quick Guide 4 | ================== 5 | 6 | Below I give a quick overview of some core functionality of svox to help get you started. 7 | Please see :ref:`svox` for detailed per-method documentation. 8 | To install the library, simply use :code:`pip install sxox`; you would of course need 9 | to install PyTorch first. 10 | You will also need the CUDA runtime to compile the CUDA extension; 11 | while the library works without the CUDA extension, it is very slow, and will emit a warning the 12 | first time a CUDA-capable operation is used. 13 | 14 | If the extension fails to build, check if your PyTorch is using the same CUDA 15 | version as you have installed on your system. 16 | 17 | Construction 18 | ------------------------------- 19 | 20 | We begin by importing the library and constructing a tree: 21 | 22 | >>> import svox 23 | >>> t=svox.N3Tree(data_dim=4, data_format="RGBA", 24 | center=[0.5, 0.5, 0.5], radius=0.5, 25 | N=2, device="cpu", 26 | init_refine=0, depth_limit=10, 27 | extra_data=None) 28 | >>> t.cuda() 29 | 30 | * :code:`data_dim` is the size of data to store in each leaf, for example 4 for :code:`RGBA` data. 31 | Since 0.2.28: this is optional if :code:`data_format` is something other than :code:`RGBA`. 32 | Since 0.2.27: an error is thrown if this is incompatible with :code:`data_format`. 33 | * :code:`data_format`, a bit redundant, is the data format for rendering (only used for VolumeRenderer). 34 | It can be :code:`RGBA`, :code:`SH#`, :code:`SG#`, or :code:`ASG#`, where # (basis_dim) is the dimensionality of the basis function. 35 | This is somewhat redundant with data_dim. 36 | data_dim should be :code:`basis_dim * 3 + 1` (Last item is always :math:`\sigma \in [0, \infty)`, the density). 37 | For SH (spherical harmonics), basis_dim must be a square number at most 25. SG (spherical Gaussians) and ASG (anisotropic SG) require :code:`extra_data` field to render properly. 38 | * :code:`radius` and :code:`center` specify the transform of the tree in space, with :code:`radius` meaning the half-edge length of the bounding cube (1 float or list of 3 floats for each axis) and :code:`center` specifying the center of the cube (list of 3 floats). By default cube is centered at :code:`[0.5, 0.5, 0.5]` with radius 0.5. 39 | * :code:`N` (optional, default 2) is the N in :math:`N^3` tree. Typically, put :code:`N=2` for an octree. 40 | * :code:`device` (optional, default cpu) can be a string like 'cuda' and is where the tree's data will be stored. 41 | * :code:`init_refine` specifies initial LOD of the tree: the initial leaf voxel size will be :code:`N^(init_refine + 1)`. 42 | * :code:`depth_limit` is a utility for limiting the maximum depth of any tree leaf after refinement. Note that the root is at depth -1, which may be a bit confusing; initially the tree has maximum depth 1 and :code:`NxNxN` leaves. 43 | * :code:`extra_data` for SG, basis_dim x 4 matrix of variance/mean (3). For ASG, data_dim x 11 matrix. 44 | Currently, optimizing wrt this matrix is not supported, so the parameters should be pre-determined. 45 | 46 | :code:`svox.N3Tree` is a PyTorch module and 47 | usual operations such as :code:`.parameters()` or :code:`.cuda()` can be used. 48 | The forward method of the N3Tree class takes a batch of points :code:`(B, 3)` and returns 49 | corresponding data. 50 | 51 | Saving and Loading 52 | ------------------------------ 53 | To save and load trees to/from npz files, use 54 | 55 | >>> tree.save(npz_path) 56 | >>> tree = svox.N3Tree.load(npz_path, device=device) 57 | 58 | 'device' can be a string like 'cuda' and is where the tree's data will be loaded into, similar 59 | to that in the constructor. 60 | Since the tree is a PyTorch module, you could also use a PyTorch checkpoint, but it can be VERY inefficient. 61 | 62 | Querying and Modifying Data using N3TreeView 63 | --------------------------------------------- 64 | 65 | For convenient query and manipulation, we provide an approximate analogy to the PyTorch tensor, 66 | where the tree is viewed as a matrix of size 67 | :code:`(n_leaves, data_dim)`. Any indexing operation into the N3Tree returns a 68 | :code:`N3TreeView` class which works like a tensor. 69 | 70 | >>> tree.shape 71 | torch.Size([8, 4]) 72 | >>> tree[0] += 1 73 | >>> tree[:, :3] 74 | N3TreeView(tensor([[1., 1., 1.], 75 | [0., 0., 0.], 76 | [0., 0., 0.], 77 | [0., 0., 0.], 78 | [0., 0., 0.], 79 | [0., 0., 0.], 80 | [0., 0., 0.], 81 | [0., 0., 0.]])) 82 | >>> tree[:, -1:] = -1 83 | >>> tree[:2] 84 | N3TreeView(tensor([[ 1., 1., 1., -1.], 85 | [ 0., 0., 0., -1.]])) 86 | 87 | You can also, of course, query the tree using *real spatial points*, 88 | by either using 3 indices or a :code:`(N, 3)` query matrix: 89 | 90 | >>> tree[0, 0.5, 0] # Query point (0, 0.5, 0) 91 | >>> tree[points] # Query points (N, 3) 92 | 93 | This returns a N3TreeView of leaves corresponding to these points, so you can also modify them: 94 | 95 | >>> tree[points] = values # Query points (N, 3), values (N, data_dim) 96 | >>> tree[0, 0, 0] /= 2.0 97 | 98 | The tree is self behaves similarly to :code:`tree[:]`. Some more examples: 99 | 100 | >>> tree += 1.5 101 | >>> tree.normal_() 102 | >>> tree[:, -1:].clamp_(0.1, None) 103 | 104 | When used with a PyTorch operation such as :code:`torch.mean` or operators like :code:`+`, 105 | the N3TreeView is queried and the values are converted to a PyTorch tensor automatically. 106 | If you wish to get the values as a tensor explicitly, use :code:`view.values`. 107 | See the section :ref:`Advanced Leaf-level Accessors` for more advanced operations supported by 108 | N3TreeView. 109 | 110 | Refinement oracle 111 | --------------------- 112 | 113 | To refine the tree, use the :code:`refine` function. 114 | The first argument allows you to refine more than once. 115 | 116 | >>> tree.refine() # Refine all nodes 117 | >>> tree.refine(2) # Refine all nodes twice 118 | >>> tree[-1].refine() # Refine leaf -1 once, through the N3TreeView 119 | 120 | Differentiable Volume Rendering 121 | --------------------------------- 122 | This is implemented in the :code:`svox.VolumeRenderer` class. 123 | The following code renders a perspective image: 124 | 125 | >>> ren = svox.VolumeRenderer(tree) 126 | >>> camera = # some [4, 4] camera pose matrix 127 | >>> ren.render_persp(camera, width=width, height=height, fx=fx) # Get a perspective image 128 | 129 | Note the renderer need not be updated if the tree is modified. 130 | The renderer will use the tree's :code:`data_format` field: 131 | one of :code:`RGBA`, :code:`SH#`, :code:`SG#`, or :code:`ASG#`, where # (basis_dim) is the dimensionality of the basis function. 132 | For SH, this must be a square number at most 25. 133 | The last dimension is always used as density :math:`\sigma \in [0, \infty)`, where the value is clipped to 0 while rendering if negative. 134 | The volume rendering formula is as in NeRF: 135 | 136 | .. math:: 137 | \mathbf{C} = \sum_{i=1}^n \left[\prod_{j=1}^{i-1}\exp(-\delta_j \sigma_j)\right] \left[1 - \exp(-\delta_i \sigma_i)\right] \mathbf{c}_i(\mathbf{d}) 138 | 139 | Where :math:`\delta_i, \sigma_i, \mathbf{c}_i` are segment i's length, density, and color, respectively. :math:`\mathbf{d}` is the viewing direction 140 | and :math:`\mathbf{C}` is the final output color. 141 | 142 | Also you can render rays directly, by using the forward method of VolumeRenderer: 143 | 144 | >>> ray = svox.Rays(origins = ... dirs=..., viewdirs=...) 145 | >>> ren(ray) 146 | 147 | You can pass :code:`fast=True` to either render_persp or this forward method 148 | to allow fast rendering (with early stopping) potentially at the cost of quality. 149 | 150 | These functions are backed by CUDA analytic derivatives. 151 | For example, 152 | 153 | >>> im = ren.render_persp(camera) 154 | >>> torch.abs(im - im_gt).mean().backward() 155 | >>> print(tree.data.grad.shape) 156 | 157 | Finally, NDC views are also internally supported in render_persp. 158 | To use this features, pass :code:`ndc=svox.NDCConfig(width=..., heigh=..., focal=...)` 159 | to the VolumeRenderer constructor. 160 | 161 | **Troubleshooting**: If you get an error about a tensor being non-contiguous, 162 | please make sure it is contiguous using 163 | :code:`.contiguous()`, for example 164 | :code:`svox.Rays(origins=r[:, :3].contiguous(), dirs=r[:, 3:6].contiguous(), viewdirs=r[:, 3:6].contiguous())`. 165 | 166 | .. _leaf_level_acc: 167 | 168 | Advanced Leaf-level Accessors 169 | ------------------------------ 170 | Some more functions for working with leaves 171 | 172 | >>> tree.lengths # Side lengths of each leaf voxel (same order as leaf matrix) 173 | >>> tree.depths # Depth of each leaf voxel (root is at **-1**) 174 | >>> tree.corners # Lowest corner of each leaf voxel 175 | >>> tree.values # Values at each leaf voxel 176 | >>> tree.sample(n_samples: int) # Sample uniformly random points in each voxel 177 | 178 | In each case you may also use N3TreeView, for example 179 | 180 | >>> tree[tree.depths==2].corners 181 | 182 | For each of lengths/corners/sample there is also a \*_local version 183 | which returns points and lengths in local coordinates :math:`[0,1]^3`. 184 | 185 | Advanced: Volume Rendering Weight Accumulator Context 186 | ------------------------------------------------------- 187 | Sometimes we want to accumulate volume rendering weights in each tree leaf, 188 | to see how much each leaf voxel was used in the rendering process. 189 | We may either want the max or total rendering weight (influence) within each voxel. 190 | We have a built-in context manager to do so. 191 | 192 | >>> with tree.accumulate_weights(op="sum") as accum: # or op="max" 193 | >>> # Do some ray/image rendering with a renderer on the tree 194 | >>> # Tree cannot be refined or shrank here 195 | >>> accum = accum() 196 | 197 | The final :code:`accum` is a float tensor of shape 198 | equal to tree.n_leaves which can 199 | be used to index into the tree. 200 | Each entry is equal to the *sum* of all volume rendering *weights* 201 | for all rays which every hit the voxel within the context. 202 | You can use it as follows: 203 | 204 | >>> tree[accum > 1.0].refine() 205 | >>> tree[accum < 1.0] += 1 206 | 207 | *Advanced*: You can also use :code:`accum.value` to grab the complete 208 | accumulated tensor of size equal to :code:`tree.data`. 209 | This is more efficient than using :code:`accum()`. 210 | -------------------------------------------------------------------------------- /docs/build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | * 33 | * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL 34 | */ 35 | jQuery.urldecode = function(x) { 36 | if (!x) { 37 | return x 38 | } 39 | return decodeURIComponent(x.replace(/\+/g, ' ')); 40 | }; 41 | 42 | /** 43 | * small helper function to urlencode strings 44 | */ 45 | jQuery.urlencode = encodeURIComponent; 46 | 47 | /** 48 | * This function returns the parsed url parameters of the 49 | * current request. Multiple values per key are supported, 50 | * it will always return arrays of strings for the value parts. 51 | */ 52 | jQuery.getQueryParameters = function(s) { 53 | if (typeof s === 'undefined') 54 | s = document.location.search; 55 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 56 | var result = {}; 57 | for (var i = 0; i < parts.length; i++) { 58 | var tmp = parts[i].split('=', 2); 59 | var key = jQuery.urldecode(tmp[0]); 60 | var value = jQuery.urldecode(tmp[1]); 61 | if (key in result) 62 | result[key].push(value); 63 | else 64 | result[key] = [value]; 65 | } 66 | return result; 67 | }; 68 | 69 | /** 70 | * highlight a given string on a jquery object by wrapping it in 71 | * span elements with the given class name. 72 | */ 73 | jQuery.fn.highlightText = function(text, className) { 74 | function highlight(node, addItems) { 75 | if (node.nodeType === 3) { 76 | var val = node.nodeValue; 77 | var pos = val.toLowerCase().indexOf(text); 78 | if (pos >= 0 && 79 | !jQuery(node.parentNode).hasClass(className) && 80 | !jQuery(node.parentNode).hasClass("nohighlight")) { 81 | var span; 82 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 83 | if (isInSVG) { 84 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 85 | } else { 86 | span = document.createElement("span"); 87 | span.className = className; 88 | } 89 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 90 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 91 | document.createTextNode(val.substr(pos + text.length)), 92 | node.nextSibling)); 93 | node.nodeValue = val.substr(0, pos); 94 | if (isInSVG) { 95 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 96 | var bbox = node.parentElement.getBBox(); 97 | rect.x.baseVal.value = bbox.x; 98 | rect.y.baseVal.value = bbox.y; 99 | rect.width.baseVal.value = bbox.width; 100 | rect.height.baseVal.value = bbox.height; 101 | rect.setAttribute('class', className); 102 | addItems.push({ 103 | "parent": node.parentNode, 104 | "target": rect}); 105 | } 106 | } 107 | } 108 | else if (!jQuery(node).is("button, select, textarea")) { 109 | jQuery.each(node.childNodes, function() { 110 | highlight(this, addItems); 111 | }); 112 | } 113 | } 114 | var addItems = []; 115 | var result = this.each(function() { 116 | highlight(this, addItems); 117 | }); 118 | for (var i = 0; i < addItems.length; ++i) { 119 | jQuery(addItems[i].parent).before(addItems[i].target); 120 | } 121 | return result; 122 | }; 123 | 124 | /* 125 | * backward compatibility for jQuery.browser 126 | * This will be supported until firefox bug is fixed. 127 | */ 128 | if (!jQuery.browser) { 129 | jQuery.uaMatch = function(ua) { 130 | ua = ua.toLowerCase(); 131 | 132 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 133 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 134 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 135 | /(msie) ([\w.]+)/.exec(ua) || 136 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 137 | []; 138 | 139 | return { 140 | browser: match[ 1 ] || "", 141 | version: match[ 2 ] || "0" 142 | }; 143 | }; 144 | jQuery.browser = {}; 145 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 146 | } 147 | 148 | /** 149 | * Small JavaScript module for the documentation. 150 | */ 151 | var Documentation = { 152 | 153 | init : function() { 154 | this.fixFirefoxAnchorBug(); 155 | this.highlightSearchWords(); 156 | this.initIndexTable(); 157 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { 158 | this.initOnKeyListeners(); 159 | } 160 | }, 161 | 162 | /** 163 | * i18n support 164 | */ 165 | TRANSLATIONS : {}, 166 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 167 | LOCALE : 'unknown', 168 | 169 | // gettext and ngettext don't access this so that the functions 170 | // can safely bound to a different name (_ = Documentation.gettext) 171 | gettext : function(string) { 172 | var translated = Documentation.TRANSLATIONS[string]; 173 | if (typeof translated === 'undefined') 174 | return string; 175 | return (typeof translated === 'string') ? translated : translated[0]; 176 | }, 177 | 178 | ngettext : function(singular, plural, n) { 179 | var translated = Documentation.TRANSLATIONS[singular]; 180 | if (typeof translated === 'undefined') 181 | return (n == 1) ? singular : plural; 182 | return translated[Documentation.PLURALEXPR(n)]; 183 | }, 184 | 185 | addTranslations : function(catalog) { 186 | for (var key in catalog.messages) 187 | this.TRANSLATIONS[key] = catalog.messages[key]; 188 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 189 | this.LOCALE = catalog.locale; 190 | }, 191 | 192 | /** 193 | * add context elements like header anchor links 194 | */ 195 | addContextElements : function() { 196 | $('div[id] > :header:first').each(function() { 197 | $('\u00B6'). 198 | attr('href', '#' + this.id). 199 | attr('title', _('Permalink to this headline')). 200 | appendTo(this); 201 | }); 202 | $('dt[id]').each(function() { 203 | $('\u00B6'). 204 | attr('href', '#' + this.id). 205 | attr('title', _('Permalink to this definition')). 206 | appendTo(this); 207 | }); 208 | }, 209 | 210 | /** 211 | * workaround a firefox stupidity 212 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 213 | */ 214 | fixFirefoxAnchorBug : function() { 215 | if (document.location.hash && $.browser.mozilla) 216 | window.setTimeout(function() { 217 | document.location.href += ''; 218 | }, 10); 219 | }, 220 | 221 | /** 222 | * highlight the search words provided in the url in the text 223 | */ 224 | highlightSearchWords : function() { 225 | var params = $.getQueryParameters(); 226 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 227 | if (terms.length) { 228 | var body = $('div.body'); 229 | if (!body.length) { 230 | body = $('body'); 231 | } 232 | window.setTimeout(function() { 233 | $.each(terms, function() { 234 | body.highlightText(this.toLowerCase(), 'highlighted'); 235 | }); 236 | }, 10); 237 | $('') 239 | .appendTo($('#searchbox')); 240 | } 241 | }, 242 | 243 | /** 244 | * init the domain index toggle buttons 245 | */ 246 | initIndexTable : function() { 247 | var togglers = $('img.toggler').click(function() { 248 | var src = $(this).attr('src'); 249 | var idnum = $(this).attr('id').substr(7); 250 | $('tr.cg-' + idnum).toggle(); 251 | if (src.substr(-9) === 'minus.png') 252 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 253 | else 254 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 255 | }).css('display', ''); 256 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 257 | togglers.click(); 258 | } 259 | }, 260 | 261 | /** 262 | * helper function to hide the search marks again 263 | */ 264 | hideSearchWords : function() { 265 | $('#searchbox .highlight-link').fadeOut(300); 266 | $('span.highlighted').removeClass('highlighted'); 267 | }, 268 | 269 | /** 270 | * make the url absolute 271 | */ 272 | makeURL : function(relativeURL) { 273 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 274 | }, 275 | 276 | /** 277 | * get the current relative url 278 | */ 279 | getCurrentURL : function() { 280 | var path = document.location.pathname; 281 | var parts = path.split(/\//); 282 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 283 | if (this === '..') 284 | parts.pop(); 285 | }); 286 | var url = parts.join('/'); 287 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 288 | }, 289 | 290 | initOnKeyListeners: function() { 291 | $(document).keydown(function(event) { 292 | var activeElementType = document.activeElement.tagName; 293 | // don't navigate when in search box, textarea, dropdown or button 294 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' 295 | && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey 296 | && !event.shiftKey) { 297 | switch (event.keyCode) { 298 | case 37: // left 299 | var prevHref = $('link[rel="prev"]').prop('href'); 300 | if (prevHref) { 301 | window.location.href = prevHref; 302 | return false; 303 | } 304 | case 39: // right 305 | var nextHref = $('link[rel="next"]').prop('href'); 306 | if (nextHref) { 307 | window.location.href = nextHref; 308 | return false; 309 | } 310 | } 311 | } 312 | }); 313 | } 314 | }; 315 | 316 | // quick alias for translations 317 | _ = Documentation.gettext; 318 | 319 | $(document).ready(function() { 320 | Documentation.init(); 321 | }); 322 | -------------------------------------------------------------------------------- /docs/build/html/ex_nerf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Example: Lego Bulldozer Rendering — svox 0.2.32-dev documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | 50 | 115 | 116 |
117 | 118 | 119 | 125 | 126 | 127 |
128 | 129 |
130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 |
150 | 151 |
    152 | 153 |
  • »
  • 154 | 155 |
  • Example: Lego Bulldozer Rendering
  • 156 | 157 | 158 |
  • 159 | 160 | 161 | View page source 162 | 163 | 164 |
  • 165 | 166 |
167 | 168 | 169 |
170 |
171 |
172 |
173 | 174 |
175 |

Example: Lego Bulldozer Rendering

176 |

In this example, we load a stored PlenOctree npz model file and render it using 177 | VolumeRenderer. 178 | You can download the npz from: 179 | https://drive.google.com/file/d/1XRi_YqdcDrfwqOqV3QPoEOZynuHAGI5M/view?usp=sharing

180 |
import svox
181 | import torch
182 | import matplotlib.pyplot as plt
183 | 
184 | device = 'cuda:0'
185 | 
186 | t = svox.N3Tree.load("lego.npz", device=device)
187 | r = svox.VolumeRenderer(t)
188 | 
189 | # Matrix copied from lego test set image 0
190 | c2w = torch.tensor([[ -0.9999999403953552, 0.0, 0.0, 0.0 ],
191 |                     [ 0.0, -0.7341099977493286, 0.6790305972099304, 2.737260103225708 ],
192 |                     [ 0.0, 0.6790306568145752, 0.7341098785400391, 2.959291696548462 ],
193 |                     [ 0.0, 0.0, 0.0, 1.0 ],
194 |              ], device=device)
195 | 
196 | with torch.no_grad():
197 |     im = r.render_persp(c2w, height=800, width=800, fx=1111.111).clamp_(0.0, 1.0)
198 | plt.imshow(im.cpu())
199 | plt.show()
200 | 
201 |
202 | _images/ex_nerf.png 203 |
204 | 205 | 206 |
207 | 208 |
209 |
210 | 214 | 215 |
216 | 217 |
218 |

219 | © Copyright 2021 Alex Yu. 220 | 221 |

222 |
223 | 224 | 225 | 226 | Built with Sphinx using a 227 | 228 | theme 229 | 230 | provided by Read the Docs. 231 | 232 |
233 |
234 |
235 | 236 |
237 | 238 |
239 | 240 | 241 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | -------------------------------------------------------------------------------- /docs/build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Welcome to the svox documentation — svox 0.2.32-dev documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 | 49 | 114 | 115 |
116 | 117 | 118 | 124 | 125 | 126 |
127 | 128 |
129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 |
149 | 150 |
    151 | 152 |
  • »
  • 153 | 154 |
  • Welcome to the svox documentation
  • 155 | 156 | 157 |
  • 158 | 159 | 160 | View page source 161 | 162 | 163 |
  • 164 | 165 |
166 | 167 | 168 |
169 |
170 |
171 |
172 | 173 |
174 |

Welcome to the svox documentation

175 |

This is a PlenOctree volume rendering implementation as a PyTorch extension with CUDA acceleration.

176 |

Note this only implements octree (or more generally N^3 tree) operations and differentiable volume rendering. It does not relate to NeRF training part of the project 177 | and does not involve a neural network.

178 |

The code is available in this repo. 179 | This is part of the code release of

180 |
181 |
PlenOctrees for Real Time Rendering of Neural Radiance Fields
182 |
Alex Yu, Ruilong Li, Matthew Tancik, Hao Li, Ren Ng, Angjoo Kanazawa
183 |
184 |
185 | 186 | 187 |
Source code (SVOX): https://github.com/sxyu/svox
188 |
189 |

Install with pip install svox.

190 |
>>> import svox
191 | >>> tree = svox.N3Tree(data_dim=4)
192 | >>> print(tree)
193 | svox.N3Tree(N=2, data_dim=4, depth_limit=10; capacity:1/1 max_depth:0)
194 | >>> tree.to('cuda:0')
195 | 
196 |
197 |

data_dim is the size of data stored at each leaf.

198 |

Please see Reference for detailed per-method documentation and Quick Guide for a quick overview of features. 199 | This is the documentation of svox version: 0.2.32-dev.

200 | 223 |
224 | 225 | 226 |
227 | 228 |
229 |
230 | 233 | 234 |
235 | 236 |
237 |

238 | © Copyright 2021 Alex Yu. 239 | 240 |

241 |
242 | 243 | 244 | 245 | Built with Sphinx using a 246 | 247 | theme 248 | 249 | provided by Read the Docs. 250 | 251 |
252 |
253 |
254 | 255 |
256 | 257 |
258 | 259 | 260 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | -------------------------------------------------------------------------------- /docs/build/html/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * language_data.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * This script contains the language-specific data used by searchtools.js, 6 | * namely the list of stopwords, stemmer, scorer and splitter. 7 | * 8 | * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; 14 | 15 | 16 | /* Non-minified version is copied as a separate JS file, is available */ 17 | 18 | /** 19 | * Porter Stemmer 20 | */ 21 | var Stemmer = function() { 22 | 23 | var step2list = { 24 | ational: 'ate', 25 | tional: 'tion', 26 | enci: 'ence', 27 | anci: 'ance', 28 | izer: 'ize', 29 | bli: 'ble', 30 | alli: 'al', 31 | entli: 'ent', 32 | eli: 'e', 33 | ousli: 'ous', 34 | ization: 'ize', 35 | ation: 'ate', 36 | ator: 'ate', 37 | alism: 'al', 38 | iveness: 'ive', 39 | fulness: 'ful', 40 | ousness: 'ous', 41 | aliti: 'al', 42 | iviti: 'ive', 43 | biliti: 'ble', 44 | logi: 'log' 45 | }; 46 | 47 | var step3list = { 48 | icate: 'ic', 49 | ative: '', 50 | alize: 'al', 51 | iciti: 'ic', 52 | ical: 'ic', 53 | ful: '', 54 | ness: '' 55 | }; 56 | 57 | var c = "[^aeiou]"; // consonant 58 | var v = "[aeiouy]"; // vowel 59 | var C = c + "[^aeiouy]*"; // consonant sequence 60 | var V = v + "[aeiou]*"; // vowel sequence 61 | 62 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 63 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 64 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 65 | var s_v = "^(" + C + ")?" + v; // vowel in stem 66 | 67 | this.stemWord = function (w) { 68 | var stem; 69 | var suffix; 70 | var firstch; 71 | var origword = w; 72 | 73 | if (w.length < 3) 74 | return w; 75 | 76 | var re; 77 | var re2; 78 | var re3; 79 | var re4; 80 | 81 | firstch = w.substr(0,1); 82 | if (firstch == "y") 83 | w = firstch.toUpperCase() + w.substr(1); 84 | 85 | // Step 1a 86 | re = /^(.+?)(ss|i)es$/; 87 | re2 = /^(.+?)([^s])s$/; 88 | 89 | if (re.test(w)) 90 | w = w.replace(re,"$1$2"); 91 | else if (re2.test(w)) 92 | w = w.replace(re2,"$1$2"); 93 | 94 | // Step 1b 95 | re = /^(.+?)eed$/; 96 | re2 = /^(.+?)(ed|ing)$/; 97 | if (re.test(w)) { 98 | var fp = re.exec(w); 99 | re = new RegExp(mgr0); 100 | if (re.test(fp[1])) { 101 | re = /.$/; 102 | w = w.replace(re,""); 103 | } 104 | } 105 | else if (re2.test(w)) { 106 | var fp = re2.exec(w); 107 | stem = fp[1]; 108 | re2 = new RegExp(s_v); 109 | if (re2.test(stem)) { 110 | w = stem; 111 | re2 = /(at|bl|iz)$/; 112 | re3 = new RegExp("([^aeiouylsz])\\1$"); 113 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 114 | if (re2.test(w)) 115 | w = w + "e"; 116 | else if (re3.test(w)) { 117 | re = /.$/; 118 | w = w.replace(re,""); 119 | } 120 | else if (re4.test(w)) 121 | w = w + "e"; 122 | } 123 | } 124 | 125 | // Step 1c 126 | re = /^(.+?)y$/; 127 | if (re.test(w)) { 128 | var fp = re.exec(w); 129 | stem = fp[1]; 130 | re = new RegExp(s_v); 131 | if (re.test(stem)) 132 | w = stem + "i"; 133 | } 134 | 135 | // Step 2 136 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 137 | if (re.test(w)) { 138 | var fp = re.exec(w); 139 | stem = fp[1]; 140 | suffix = fp[2]; 141 | re = new RegExp(mgr0); 142 | if (re.test(stem)) 143 | w = stem + step2list[suffix]; 144 | } 145 | 146 | // Step 3 147 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 148 | if (re.test(w)) { 149 | var fp = re.exec(w); 150 | stem = fp[1]; 151 | suffix = fp[2]; 152 | re = new RegExp(mgr0); 153 | if (re.test(stem)) 154 | w = stem + step3list[suffix]; 155 | } 156 | 157 | // Step 4 158 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 159 | re2 = /^(.+?)(s|t)(ion)$/; 160 | if (re.test(w)) { 161 | var fp = re.exec(w); 162 | stem = fp[1]; 163 | re = new RegExp(mgr1); 164 | if (re.test(stem)) 165 | w = stem; 166 | } 167 | else if (re2.test(w)) { 168 | var fp = re2.exec(w); 169 | stem = fp[1] + fp[2]; 170 | re2 = new RegExp(mgr1); 171 | if (re2.test(stem)) 172 | w = stem; 173 | } 174 | 175 | // Step 5 176 | re = /^(.+?)e$/; 177 | if (re.test(w)) { 178 | var fp = re.exec(w); 179 | stem = fp[1]; 180 | re = new RegExp(mgr1); 181 | re2 = new RegExp(meq1); 182 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 183 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 184 | w = stem; 185 | } 186 | re = /ll$/; 187 | re2 = new RegExp(mgr1); 188 | if (re.test(w) && re2.test(w)) { 189 | re = /.$/; 190 | w = w.replace(re,""); 191 | } 192 | 193 | // and turn initial Y back to y 194 | if (firstch == "y") 195 | w = firstch.toLowerCase() + w.substr(1); 196 | return w; 197 | } 198 | } 199 | 200 | 201 | 202 | 203 | var splitChars = (function() { 204 | var result = {}; 205 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, 206 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, 207 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, 208 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, 209 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, 210 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, 211 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, 212 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, 213 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, 214 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; 215 | var i, j, start, end; 216 | for (i = 0; i < singles.length; i++) { 217 | result[singles[i]] = true; 218 | } 219 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], 220 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], 221 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], 222 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], 223 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], 224 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], 225 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], 226 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], 227 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], 228 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], 229 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], 230 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], 231 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], 232 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], 233 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], 234 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], 235 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], 236 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], 237 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], 238 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], 239 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], 240 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], 241 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], 242 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], 243 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], 244 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], 245 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], 246 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], 247 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], 248 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], 249 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], 250 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], 251 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], 252 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], 253 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], 254 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], 255 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], 256 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], 257 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], 258 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], 259 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], 260 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], 261 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], 262 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], 263 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], 264 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], 265 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], 266 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], 267 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; 268 | for (i = 0; i < ranges.length; i++) { 269 | start = ranges[i][0]; 270 | end = ranges[i][1]; 271 | for (j = start; j <= end; j++) { 272 | result[j] = true; 273 | } 274 | } 275 | return result; 276 | })(); 277 | 278 | function splitQuery(query) { 279 | var result = []; 280 | var start = -1; 281 | for (var i = 0; i < query.length; i++) { 282 | if (splitChars[query.charCodeAt(i)]) { 283 | if (start !== -1) { 284 | result.push(query.slice(start, i)); 285 | start = -1; 286 | } 287 | } else if (start === -1) { 288 | start = i; 289 | } 290 | } 291 | if (start !== -1) { 292 | result.push(query.slice(start)); 293 | } 294 | return result; 295 | } 296 | 297 | 298 | -------------------------------------------------------------------------------- /docs/build/html/_static/js/modernizr.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f= 3: 33 | # Handle tree[x, y, z[, c]] 34 | main_key = torch.tensor(key[:3], dtype=tree.data.dtype, 35 | device=tree.data.device).reshape(1, 3) 36 | if len(key) > 3: 37 | key = (main_key, *key[3:]) 38 | else: 39 | key = main_key 40 | leaf_key = key[0] if isinstance(key, tuple) else key 41 | if isinstance(leaf_key, LocalIndex): 42 | leaf_key = leaf_key.val 43 | local = True 44 | if torch.is_tensor(leaf_key) and leaf_key.ndim == 2 and leaf_key.shape[1] == 3: 45 | # Handle tree[P[, c]] where P is a (B, 3) matrix of 3D points 46 | if leaf_key.dtype != tree.data.dtype: 47 | leaf_key = leaf_key.to(dtype=tree.data.dtype) 48 | val, target = tree.forward(leaf_key, want_node_ids=True, world=not local) 49 | self._packed_ids = target.clone() 50 | leaf_node = (*tree._unpack_index(target).T,) 51 | else: 52 | self._packed_ids = None 53 | if isinstance(leaf_key, int): 54 | leaf_key = torch.tensor([leaf_key], device=tree.data.device) 55 | self.single_key = True 56 | leaf_node = self.tree._all_leaves() 57 | leaf_node = leaf_node.__getitem__(leaf_key).T 58 | if isinstance(key, tuple): 59 | self.key = (*leaf_node, *key[1:]) 60 | else: 61 | self.key = (*leaf_node,) 62 | self._value = None 63 | self._tree_ver = tree._ver 64 | 65 | def __repr__(self): 66 | self._check_ver() 67 | return "N3TreeView(" + repr(self.values) + ")" 68 | 69 | def __torch_function__(self, func, types, args=(), kwargs=None): 70 | self._check_ver() 71 | if kwargs is None: 72 | kwargs = {} 73 | new_args = [] 74 | for arg in args: 75 | if isinstance(arg, N3TreeView): 76 | new_args.append(arg.values) 77 | else: 78 | new_args.append(arg) 79 | return func(*new_args, **kwargs) 80 | 81 | def set(self, value): 82 | self._check_ver() 83 | if isinstance(value, N3TreeView): 84 | value = value.values_nograd 85 | if self._require_subindex(): 86 | tmp = self.tree.data.data[self.key[:-1]] 87 | tmp[..., self.key[-1]] = value 88 | self.tree.data.data[self.key[:-1]] = tmp 89 | else: 90 | self.tree.data.data[self.key] = value 91 | 92 | def refine(self, repeats=1): 93 | """ 94 | Refine selected leaves using tree.refine 95 | """ 96 | self._check_ver() 97 | ret = self.tree.refine(repeats, sel=self._unique_node_key()) 98 | return ret 99 | 100 | @property 101 | def values(self): 102 | """ 103 | Values of the selected leaves (autograd enabled) 104 | 105 | :return: (n_leaves, data_dim) float32 note this is 2D even if key is int 106 | """ 107 | self._check_ver() 108 | if self._require_subindex(): 109 | ret = self.tree.data[self.key[:-1]][..., self.key[-1]] 110 | else: 111 | ret = self.tree.data[self.key] 112 | return ret[0] if self.single_key else ret 113 | 114 | @property 115 | def values_nograd(self): 116 | """ 117 | Values of the selected leaves (no autograd) 118 | 119 | :return: (n_leaves, data_dim) float32 note this is 2D even if key is int 120 | """ 121 | self._check_ver() 122 | if self._require_subindex(): 123 | ret = self.tree.data.data[self.key[:-1]][..., self.key[-1]] 124 | else: 125 | ret = self.tree.data[self.key] 126 | return ret[0] if self.single_key else ret 127 | 128 | @property 129 | def shape(self): 130 | self._check_ver() 131 | return self.values_nograd.shape 132 | 133 | @property 134 | def ndim(self): 135 | return 2 136 | 137 | @property 138 | def depths(self): 139 | """ 140 | Get a list of selected leaf depths in tree, 141 | in same order as values, corners. 142 | Root is at depth -1. Any children of 143 | root will have depth 0, etc. 144 | 145 | :return: (n_leaves) int32 146 | """ 147 | self._check_ver() 148 | return self.tree.parent_depth[self.key[0], 1] 149 | 150 | @property 151 | def lengths(self): 152 | """ 153 | Get a list of selected leaf side lengths in tree (world dimensions), 154 | in same order as values, corners, depths 155 | 156 | :return: (n_leaves, 3) float 157 | """ 158 | self._check_ver() 159 | return (self.tree.N ** (-self.depths.float() - 1.0))[:, None] / self.tree.invradius 160 | 161 | @property 162 | def lengths_local(self): 163 | """ 164 | Get a list of selected leaf side lengths in tree 165 | (local index :math:`[0, 1]^3`), 166 | in same order as values, corners, depths 167 | 168 | :return: (n_leaves) float 169 | """ 170 | self._check_ver() 171 | return self.tree.N ** (-self.depths.float() - 1.0) 172 | 173 | @property 174 | def corners(self): 175 | """ 176 | Get a list of selected leaf lower corners in tree 177 | (world coordinates), 178 | in same order as values, lengths, depths 179 | 180 | :return: (n_leaves, 3) float 181 | """ 182 | self._check_ver() 183 | return (self.tree._calc_corners(self._indexer()) 184 | - self.tree.offset) / self.tree.invradius 185 | 186 | @property 187 | def corners_local(self): 188 | """ 189 | Get a list of selected leaf lower corners in tree 190 | (local index :math:`[0, 1]^3`), 191 | in same order as values, lengths, depths 192 | 193 | :return: (n_leaves, 3) float 194 | """ 195 | self._check_ver() 196 | return self.tree._calc_corners(self._indexer()) 197 | 198 | def sample(self, n_samples, device=None): 199 | """ 200 | Sample n_samples uniform points in each selected leaf (world coordinates) 201 | 202 | :param n_samples: samples for each leaf 203 | :param device: device to output random samples in 204 | 205 | :return: (n_leaves, n_samples, 3) float 206 | """ 207 | self._check_ver() 208 | if device is None: 209 | device = self.tree.data.device 210 | corn = self.corners.to(device=device) 211 | length = self.lengths.to(device=device) 212 | if length.ndim == 1: 213 | length = length[:, None] 214 | u = torch.rand((corn.shape[0], n_samples, 3), 215 | device=device, 216 | dtype=length.dtype) * length[:, None] 217 | return corn[:, None] + u 218 | 219 | def sample_local(self, n_samples): 220 | """ 221 | Sample n_samples uniform points in each selected leaf 222 | (local index :math:`[0, 1]^3`) 223 | 224 | :return: (n_leaves, n_samples, 3) float 225 | """ 226 | self._check_ver() 227 | corn = self.corners_local 228 | length = self.lengths_local 229 | u = torch.rand((corn.shape[0], n_samples, 3), 230 | device=length.device, 231 | dtype=length.dtype) * length[:, None, None] 232 | return corn[:, None] + u 233 | 234 | def aux(self, arr): 235 | """ 236 | Index an auxiliary tree data array of size (capacity, N, N, N, Any) 237 | using this view 238 | """ 239 | if self._require_subindex(): 240 | return arr[self.key[:-1]][..., self.key[-1]] 241 | else: 242 | return arr[self.key] 243 | 244 | # In-place modification helpers 245 | def normal_(self, mean=0.0, std=1.0): 246 | """ 247 | Set all values to random normal 248 | FIXME: inefficient 249 | 250 | :param mean: normal mean 251 | :param std: normal std 252 | 253 | """ 254 | self._check_ver() 255 | self.set(torch.randn_like(self.values_nograd) * std + mean) 256 | 257 | def uniform_(self, min=0.0, max=1.0): 258 | """ 259 | Set all values to random uniform 260 | FIXME: inefficient 261 | 262 | :param min: interval min 263 | :param max: interval max 264 | 265 | """ 266 | self._check_ver() 267 | self.set(torch.rand_like(self.values_nograd) * (max - min) + min) 268 | 269 | def clamp_(self, min=None, max=None): 270 | """ 271 | Clamp. 272 | FIXME: inefficient 273 | 274 | :param min: clamp min value, None=disable 275 | :param max: clamp max value, None=disable 276 | 277 | """ 278 | self._check_ver() 279 | self.set(torch.clamp(self.values_nograd, min, max)) 280 | 281 | def relu_(self): 282 | """ 283 | Apply relu to all elements. 284 | FIXME: inefficient 285 | """ 286 | self._check_ver() 287 | self.set(torch.relu(self.values_nograd)) 288 | 289 | def sigmoid_(self): 290 | """ 291 | Apply sigmoid to all elements. 292 | FIXME: inefficient 293 | """ 294 | self._check_ver() 295 | self.set(torch.sigmoid(self.values_nograd)) 296 | 297 | def nan_to_num_(self, inf_val=2e4): 298 | """ 299 | Convert nans to 0.0 and infs to inf_val 300 | FIXME: inefficient 301 | """ 302 | data = self.tree.data.data[self.key] 303 | data[torch.isnan(data)] = 0.0 304 | inf_mask = torch.isinf(data) 305 | data[inf_mask & (data > 0)] = inf_val 306 | data[inf_mask & (data < 0)] = -inf_val 307 | self.tree.data.data[self.key] = data 308 | 309 | def __setitem__(self, key, value): 310 | """ 311 | FIXME: inefficient 312 | """ 313 | val = self.values_nograd 314 | val.__setitem__(key, value) 315 | self.set(val) 316 | 317 | def _indexer(self): 318 | return torch.stack(self.key[:4], dim=-1) 319 | 320 | def _require_subindex(self): 321 | return isinstance(self.key, tuple) and len(self.key) == 5 and \ 322 | not isinstance(self.key[-1], slice) and not isinstance(self.key[-1], int) 323 | 324 | def _unique_node_key(self): 325 | if self._packed_ids is None: 326 | return self.key[:4] 327 | 328 | uniq_ids = torch.unique(self._packed_ids) 329 | return (*self.tree._unpack_index(uniq_ids).T,) 330 | 331 | def _check_ver(self): 332 | if self.tree._ver > self._tree_ver: 333 | self.key = self._packed_ids = None 334 | raise RuntimeError("N3TreeView has been invalidated because tree " + 335 | "data layout has changed") 336 | 337 | # Redirect functions to Tensor 338 | def _redirect_funcs(): 339 | redir_funcs = ['__floordiv__', '__mod__', '__div__', 340 | '__eq__', '__ne__', '__ge__', '__gt__', '__le__', 341 | '__lt__', '__floor__', '__ceil__', '__round__', '__len__', 342 | 'item', 'size', 'dim', 'numel'] 343 | redir_grad_funcs = ['__add__', '__mul__', '__sub__', 344 | '__mod__', '__div__', '__truediv__', 345 | '__radd__', '__rsub__', '__rmul__', 346 | '__rdiv__', '__abs__', '__pos__', '__neg__', 347 | '__len__', 'clamp', 'clamp_max', 'clamp_min', 'relu', 'sigmoid', 348 | 'max', 'min', 'mean', 'sum', '__getitem__'] 349 | def redirect_func(redir_func, grad=False): 350 | def redir_impl(self, *args, **kwargs): 351 | return getattr(self.values if grad else self.values_nograd, redir_func)( 352 | *args, **kwargs) 353 | setattr(N3TreeView, redir_func, redir_impl) 354 | for redir_func in redir_funcs: 355 | redirect_func(redir_func) 356 | for redir_func in redir_grad_funcs: 357 | redirect_func(redir_func, grad=True) 358 | _redirect_funcs() 359 | 360 | 361 | def _get_c_extension(): 362 | from warnings import warn 363 | try: 364 | import svox.csrc as _C 365 | if not hasattr(_C, "query_vertical"): 366 | _C = None 367 | except: 368 | _C = None 369 | 370 | if _C is None: 371 | warn("CUDA extension svox.csrc could not be loaded! " + 372 | "Operations will be slow.\n" + 373 | "Please do not import svox in the SVOX source directory.") 374 | return _C 375 | 376 | class LocalIndex: 377 | """ 378 | To query N3Tree using 'local' index :math:`[0,1]^3`, 379 | tree[LocalIndex(points)] where points (N, 3) 380 | """ 381 | def __init__(self, val): 382 | self.val = val 383 | 384 | class DataFormat: 385 | RGBA = 0 386 | SH = 1 387 | SG = 2 388 | ASG = 3 389 | def __init__(self, txt): 390 | nonalph_idx = [c.isalpha() for c in txt] 391 | if False in nonalph_idx: 392 | nonalph_idx = nonalph_idx.index(False) 393 | self.basis_dim = int(txt[nonalph_idx:]) 394 | format_type = txt[:nonalph_idx] 395 | assert self.basis_dim > 0, "data_format basis_dim must be positive" 396 | self.data_dim = 3 * self.basis_dim + 1 397 | if format_type == "SH": 398 | self.format = DataFormat.SH 399 | assert int(self.basis_dim ** 0.5) ** 2 == self.basis_dim, \ 400 | "SH basis dim must be square number" 401 | assert self.basis_dim <= 25, "SH only supported up to basis_dim 25" 402 | elif format_type == "SG": 403 | self.format = DataFormat.SG 404 | elif format_type == "ASG": 405 | self.format = DataFormat.ASG 406 | else: 407 | self.format = DataFormat.RGBA 408 | else: 409 | self.format = DataFormat.RGBA 410 | self.basis_dim = -1 411 | self.data_dim = None 412 | 413 | def __repr__(self): 414 | if self.format == DataFormat.SH: 415 | r = "SH" 416 | elif self.format == DataFormat.SG: 417 | r = "SG" 418 | elif self.format == DataFormat.ASG: 419 | r = "ASG" 420 | else: 421 | r = "RGBA" 422 | if self.basis_dim >= 0: 423 | r += str(self.basis_dim) 424 | return r 425 | --------------------------------------------------------------------------------