Metadata-Version: 2.2
Name: nanovdb-editor-dev
Version: 0.1.8rc1
Summary: NanoVDB Editor Python Module
Keywords: nanovdb,volume,rendering,gaussian,splatting,3d
Author: The OpenVDB Project contributors
License: Apache-2.0
Project-URL: Homepage, https://github.com/openvdb/nanovdb-editor
Project-URL: Repository, https://github.com/openvdb/nanovdb-editor
Project-URL: Documentation, https://github.com/openvdb/nanovdb-editor/tree/main/pymodule
Requires-Python: >=3.8
Description-Content-Type: text/markdown

##  NanoVDB Editor

Prerequisities:
- `numpy`

### Running in Docker
To run the editor in the docker container, the Dockerfile needs to contain:
```dockerfile
EXPOSE 8080

ENV NVIDIA_DRIVER_CAPABILITIES compute,graphics,utility

RUN apt-get update \
    && apt-get install -y \
    libxext6 \
    libegl1
```
Then run with the NVIDIA runtime selected (https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html):
```sh
docker run --runtime=nvidia --net=host --gpus=all ...
```

### Hello World

```py
import nanovdb_editor as nve

with nve.create_default() as app:
    # Python-friendly kwargs (or pass make_editor_config(...))
    app.show(ip="127.0.0.1", port=8080)
    # Headless/streaming: app.run(gui=False, headless=True, streaming=True, ...)
# Session closes here: worker stopped, editor shut down, compiler destroyed
```

### Pipelines

The editor's process pipelines can build NanoVDB grids from higher-level inputs
directly in Python:

```py
with nve.create_default() as app:
    scene = app.scene("main")

    nvdb = scene.nanovdb_from_gaussians(
        means=means, quats=quats, scales=scales,
        sh_0=sh_0, sh_n=sh_n, opacities=opacities,
        process="voxelbvh", resolution=512,
    )

    # Bake colors to an RGBA8 image grid, and choose how it's drawn
    rgba8 = scene.nanovdb_to_rgba8(nvdb, name="splats_rgba8", register=False)
    scene.set_render_pipeline("gaussians", "voxelbvh_rgba8_render")
```

You can also load an existing grid (`scene.nanovdb_from_file("grid.nvdb")`),
tune per-object parameters (`scene.set_voxels_per_unit("gaussians", 256)`,
`scene.set_resolution(...)`, `scene.set_inflation_radius(...)`),
build multi-step process chains (`scene.process_steps("mesh").append(...)`), bake
RGBA8 for several ray directions at once
(`scene.nanovdb_to_rgba8_directions(...)`), and manage scene objects with
`scene.remove` / `scene.add_grid` / `scene.update_camera` / `scene.add_image2d`.

The returned `Grid` is a context manager, and `grid.map(dtype)` hands you a
live, zero-copy NumPy view of its bytes that is unmapped on block exit:

```py
import numpy as np

with scene.nanovdb_from_mesh(indices=indices, positions=positions, register=False) as grid:
    with grid.map(np.uint32) as view:   # writes go back to the grid
        print(int(view[0]))
    grid.save("mesh.nvdb")
```

See [PIPELINES.md](PIPELINES.md) for the available pipelines, options, and a
guide to exposing (pythonizing) more of them.

### CPU NanoVDB buffers

Pass raw, uncompressed grid bytes directly from a simulation. The buffer is
copied into editor-owned memory, so the source can be released after the call:

```py
with nve.create_default() as app:
    scene = app.scene("smoke")
    with scene.nanovdb_from_buffer(
        smoke_bytes + temperature_bytes,
        name="smoke",
        shader="editor/flow_smoke.slang",
        shader_parameters={"attenuation": 0.05},
    ):
        app.show()
```

`bytes`, `bytearray`, contiguous `memoryview`, and contiguous NumPy arrays are
accepted. Supply raw NanoVDB grids, without a compressed `.nvdb` file header.
Concatenated grids are kept in order; the shader defines their interpretation.
The Flow shader reads smoke first and optional temperature second. Header and
size checks do not replace validation of the tree data by the producer.

The buffer is registered before the optional material update. If that update
fails, the object keeps the registered buffer and its current material.

`nanovdb_from_buffer` creates a missing object. Reusing an in-memory NanoVDB
object's name updates its source and preserves its material and pipelines.
Explicit shader options apply new material settings. Set compatible shader and
pipeline settings when changing the grid representation. Its returned `Grid`
owns a separate copy and can be closed immediately after registration.
Use `register=False` to create an owned grid without adding it to the scene.

For live simulation, set the material on the first frame, then omit shader options
and close each returned `Grid`; see the [Flow streaming example](../docs/flow-smoke.md).
The lower-level `Editor.add_nanovdb_2()` accepts a borrowed
compute-array descriptor and makes only the editor-owned copy. The renderer
uses the latest buffer on its next frame; submissions do not wait for a frame
or accumulate queued copies.

`scene.set_shader(name, path, parameters={...})` compiles a custom shader and
sets per-object values by reflected field name. Unspecified values use the
shader's JSON defaults. Invalid fields and values raise an error without
changing an existing shader assignment.

### Application controls

Named scenes and replaceable scene objects follow the same ownership pattern as
[fVDB's visualization API](https://github.com/openvdb/fvdb-core/tree/main/fvdb/viz).
Use custom scene parameters to connect application logic to editor controls:

```py
scene.set_custom_params({"SceneParams": {
    "Play": {"type": "bool", "value": True,
             "widget": "toggleButton", "activeLabel": "Stop"},
    "Restart": {"type": "bool", "value": False,
                "widget": "button", "sameLine": True, "tooltip": "Reload the simulation"},
    "Frame": {"type": "uint", "value": 0, "readOnly": True},
}})

with scene.custom_params() as controls:
    playing = controls["Play"]
    restart = controls["Restart"]
    controls["Restart"] = False
    controls["Frame"] = frame_number
# Advance the application after releasing the mapped controls.
```

The mapping reads current UI values and writes application values. It supports
scalar numbers, booleans, strings, and numeric tuples. Field names are dictionary
keys and can contain spaces. The mapping is valid only inside the context;
returned values are copies. Use `dict(controls)` to copy all values at once.
The context locks UI access, so
keep it short and do simulation work after it exits. Grid registration and live
buffer updates and `set_shader` can run inside the context. Do not call editor
lifecycle methods, save or load scenes, or reload the schema inside a mapped
context. Schema updates from other Python
threads wait for the context to exit. Direct native calls are outside this
Python lock.

Scalar boolean fields support `widget="button"` and `widget="toggleButton"`.
A button latches its value to true; the application reads and clears it to
acknowledge the action. Multiple clicks before that clear represent one pending
action. A toggle button flips its value and uses `activeLabel`, if supplied,
when true. `sameLine: true` places a field beside the preceding visible field;
`tooltip` supplies hover text. Without `widget`, fields keep their usual controls.

`readOnly` disables UI edits, while Python can still publish status. With
`ui_profile="nvflow"`, the title is "NanoVDB Editor - NvFlow" and the layout is
the same as `ui_profile="viewer"` (fVDB). Custom scene controls appear in
**Params**. Shader material controls,
including color ramps, appear in **Properties**. Controls define state only: the application must poll and implement
actions such as play or restart. No callbacks execute on the render thread.

### Shader Parameters
Shaders can have defined struct with shader parameters which are intended to be shown in the editor's UI:
```hlsl
struct shader_params_t
{
    float4 color;
    bool use_color;
    bool3 _pad1;
    int _pad2;
};
ConstantBuffer<shader_params_t> shader_params;
```

Shader parameters can have defined default values in the json file:
```json
{
    "ShaderParams": {
        "color": {
            "value": [1.0, 0.0, 1.0, 1.0],
            "min": 0.0,
            "max": 1.0,
            "step": 0.01
        }
    }
}
```
Supported types: `bool`, `int`, `uint`, `int64`, `uint64`, `float` and its vectors and 4x4 matrix.
Variables with `_pad` in the name are not shown in the UI.
Those parameters can be interactively changed with generated UI in the editor's Params tab.

A scalar `uint` count field can combine several parameters into a color ramp:

```json
{
    "ShaderParams": {
        "count": {
            "value": 2,
            "widget": "colorRamp",
            "label": "Color ramp",
            "positions": ["positions"],
            "colors": ["cold", "hot"]
        },
        "positions": {"value": [0.0, 1.0]},
        "cold": {"value": [0.1, 0.2, 1.0, 0.8]},
        "hot": {"value": [1.0, 0.2, 0.0, 0.8]}
    }
}
```

Declare the corresponding shader buffer in this order:

```slang
struct shader_params_t
{
    float4 cold;
    float4 hot;
    float2 positions;
    uint count;
};
ConstantBuffer<shader_params_t> shader_params;
```

The editor packs fields in declaration order without alignment padding and
omits `_pad` fields. The layout above matches the default Vulkan settings;
GPU offsets must match the packed offsets. JSON key order has no effect.

`positions` must supply one 32-bit float component per `float4` color slot.
The first `count` slots are active, with `count` between 1 and `colors.length`.
All bound fields must be visible and all slots finite, including inactive slots.
Invalid bindings show ordinary controls with a diagnostic.

Slots may be unsorted. Match the preview by interpolating RGBA linearly,
using the later slot at duplicate positions and holding endpoint colors outside
the range.

Optional `label` and `tooltip` customize the text.

To display a group of shader parameters from different shaders define a json file with various shader paths:
```json
{
    "ShaderParams": [
        "editor/editor.slang",
        "test/test.slang"
    ]
}
```

## Acknowledgements

This project makes use of the following libraries:

- [zlib](https://github.com/madler/zlib) – Compression library
- [c-blosc](https://github.com/Blosc/c-blosc) – High-performance compressor optimized for binary data
- [Vulkan-Headers](https://github.com/KhronosGroup/Vulkan-Headers) – Vulkan API headers
- [Vulkan-Loader](https://github.com/KhronosGroup/Vulkan-Loader) – Vulkan ICD loader
- [GLFW](https://github.com/glfw/glfw) – Windowing, context, and input (optional)
- [Dear ImGui](https://github.com/ocornut/imgui) – Immediate-mode GUI
- [ImGuiFileDialog](https://github.com/aiekick/ImGuiFileDialog) – File dialog for Dear ImGui
- [ImGuiColorTextEdit](https://github.com/goossens/ImGuiColorTextEdit) – Syntax-highlighted text/code editor widget
- [Slang](https://github.com/shader-slang/slang) – Shading language and compiler
- [filewatch](https://github.com/ThomasMonkman/filewatch) – Cross-platform file watching
- [JSON for Modern C++](https://github.com/nlohmann/json) – JSON serialization for C++
- [cnpy](https://github.com/rogersce/cnpy) – Read/write NumPy .npy/.npz files from C++
- [zstr](https://github.com/mateidavid/zstr) – Transparent zlib iostream wrappers
- [llhttp](https://github.com/nodejs/llhttp) – High-performance HTTP parser
- [Asio](https://github.com/chriskohlhoff/asio) – Asynchronous networking and concurrency primitives
- [RESTinio](https://github.com/Stiffstream/restinio) – Lightweight HTTP server framework
- [fmt](https://github.com/fmtlib/fmt) – Modern formatting library
- [argparse](https://github.com/morrisfranken/argparse) – Header-only argument parser for C++17
- [expected-lite](https://github.com/martinmoene/expected-lite) – std::expected-like type for C++11/14/17
- [libE57Format](https://github.com/asmaloney/libE57Format) – E57 point cloud IO (optional)
- [OpenH264](https://github.com/cisco/openh264) – H.264 encoder (optional)
- [GoogleTest](https://github.com/google/googletest) – C++ testing framework

Many thanks to the authors and contributors of these projects.
