Skip to content

Commit

Permalink
API cleanup, icon tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
brentyi committed Apr 20, 2023
1 parent fff0a1e commit 419fac6
Show file tree
Hide file tree
Showing 34 changed files with 502 additions and 346 deletions.
1 change: 0 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ jobs:
docs:
runs-on: ubuntu-latest
steps:

# Check out source
- uses: actions/checkout@v2

Expand Down
31 changes: 15 additions & 16 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,21 @@ on:

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.8'
- name: Install dependencies
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install
- name: Build and publish
env:
PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }}
PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
poetry publish --build --username $PYPI_USERNAME --password $PYPI_PASSWORD
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.8"
- name: Install dependencies
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install
- name: Build and publish
env:
PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }}
PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
poetry publish --build --username $PYPI_USERNAME --password $PYPI_PASSWORD
28 changes: 20 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# viser
<h1>
<img src="https://brentyi.github.io/viser/_static/viser.svg" height="34px" />
viser
</h1>

**[ [API Reference](https://brentyi.github.io/viser) ]** &nbsp;&nbsp;&bull;&nbsp;&nbsp; `pip install viser`
**`pip install viser`** &nbsp;&nbsp;&bull;&nbsp;&nbsp; **[
[API Reference](https://brentyi.github.io/viser) ]**

![pyright](https://github.com/brentyi/viser/workflows/pyright/badge.svg)
![mypy](https://github.com/brentyi/viser/workflows/mypy/badge.svg)
Expand All @@ -10,20 +14,29 @@
---

`viser` is a library for interactive 3D visualization + Python, inspired by
our favorite bits of the
[Nerfstudio viewer](https://github.com/nerfstudio-project/nerfstudio),
[Pangolin](https://github.com/stevenlovegrove/Pangolin),
tools like [Pangolin](https://github.com/stevenlovegrove/Pangolin),
[rviz](https://wiki.ros.org/rviz/), and
[meshcat](https://github.com/rdeits/meshcat).

Core features:
As a standalone visualization tool, `viser` features include:

- Web interface for easy use on remote machines.
- Pure-Python API for sending 3D primitives to the browser.
- Python API for sending 3D primitives to the browser.
- Python-configurable inputs: buttons, checkboxes, text inputs, sliders,
dropdowns, gizmos.
- Support for multiple panels and view-synchronized connections.

The `viser.infra` backend can also be used to build custom web applications
(example:
[the Nerfstudio viewer](https://github.com/nerfstudio-project/nerfstudio)). It
supports:

- Websocket / HTTP server management, on a shared port.
- Asynchronous server/client communication infrastructure.
- Client state persistence logic.
- Typed serialization; synchronization between Python dataclass and TypeScript
interfaces.

## Running examples

```bash
Expand Down Expand Up @@ -60,7 +73,6 @@ yarn start

https://user-images.githubusercontent.com/6992947/228734499-87d8a12a-df1a-4511-a4e0-0a46bd8532fd.mov


### Interactive NeRF rendering

(code not released)
Expand Down
7 changes: 7 additions & 0 deletions docs/source/_static/css/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
img.sidebar-logo {
width: 3em;
margin: 1em 0 0 0;
}
.sidebar-brand-text {
display: none;
}
33 changes: 33 additions & 0 deletions docs/source/_static/viser.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
"class": "",
},
],
# "light_logo": "logo-light.svg",
# "dark_logo": "logo-dark.svg",
"light_logo": "viser.svg",
"dark_logo": "viser.svg",
}

# Pull documentation types from hints
Expand Down Expand Up @@ -246,7 +246,7 @@ def docstring(app, what, name, obj, options, lines):

def setup(app):
app.connect("autodoc-process-docstring", docstring)
app.add_css_file("css/compact_table_header.css")
app.add_css_file("css/custom.css")


# Generate name aliases
Expand Down
19 changes: 14 additions & 5 deletions docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,29 @@
|mypy| |nbsp| |pyright| |nbsp| |typescript| |nbsp| |versions|

`viser` is a library for interactive 3D visualization + Python, inspired by
our favorite bits of the
[Nerfstudio viewer](https://github.com/nerfstudio-project/nerfstudio),
[Pangolin](https://github.com/stevenlovegrove/Pangolin),
tools like [Pangolin](https://github.com/stevenlovegrove/Pangolin),
[rviz](https://wiki.ros.org/rviz/), and
[meshcat](https://github.com/rdeits/meshcat).

Core features:
As a standalone visualization tool, `viser` features include:

- Web interface for easy use on remote machines.
- Pure-Python API for sending 3D primitives to the browser.
- Python API for sending 3D primitives to the browser.
- Python-configurable inputs: buttons, checkboxes, text inputs, sliders,
dropdowns, gizmos.
- Support for multiple panels and view-synchronized connections.

The `viser.infra` backend can also be used to build custom web applications
(example:
[the Nerfstudio viewer](https://github.com/nerfstudio-project/nerfstudio)). It
supports:

- Websocket / HTTP server management, on a shared port.
- Asynchronous server/client communication infrastructure.
- Client state persistence logic.
- Typed serialization; synchronization between Python dataclass and TypeScript
interfaces.

## Running examples

```bash
Expand Down
5 changes: 3 additions & 2 deletions examples/0_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
wxyz=(1.0, 0.0, 0.0, 0.0),
position=(random.random() * 2.0, 2.0, 0.2),
)
server.add_frame(
leaf = server.add_frame(
"/tree/branch/leaf",
wxyz=(1.0, 0.0, 0.0, 0.0),
position=(random.random() * 2.0, 2.0, 0.2),
)
time.sleep(5.0)

server.remove_scene_node("/tree/branch/leaf")
# Remove the leaf node from the scene.
leaf.remove()
time.sleep(0.5)
7 changes: 4 additions & 3 deletions examples/2_camera_poses.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
# This will run whenever we get a new camera!
@client.on_camera_update
def camera_update(client: viser.ClientHandle) -> None:
print("New camera", client.get_camera())
print("New camera", client.camera)

# Show the client ID in the GUI.
client.add_gui_text("Info", initial_value=f"Client {id}").set_disabled(True)
gui_info = client.add_gui_text("Info", initial_value=f"Client {id}")
gui_info.disabled = True

camera = client.get_camera()
camera = client.camera
print(f"Camera pose for client {id}")
print(f"\twxyz: {camera.wxyz}")
print(f"\tposition: {camera.position}")
Expand Down
4 changes: 2 additions & 2 deletions examples/3_client_targeted.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@

for id, client in clients.items():
# Match the image rotation of this particular client to face its camera.
camera = client.get_camera()
camera = client.camera
client.add_frame("/main", wxyz=camera.wxyz, position=(0, 0, 0), show_axes=False)

# Kind of fun: send our own camera to all of the other clients. This lets each
# connected client see the other clients.
for other in clients.values():
if client.client_id == other.client_id:
continue
camera = client.get_camera()
camera = client.camera
other.add_frame(
f"/client_{client.client_id}",
wxyz=camera.wxyz,
Expand Down
44 changes: 23 additions & 21 deletions examples/4_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ def main():
counter = 0

with server.gui_folder("Read-only"):
gui_counter = server.add_gui_number(
"Counter", initial_value=counter
).set_disabled(True)
gui_counter = server.add_gui_number("Counter", initial_value=counter)
gui_counter.disabled = True

gui_slider = server.add_gui_slider(
"Slider", min=0, max=100, step=1, initial_value=counter
).set_disabled(True)
)
gui_slider.disabled = True

with server.gui_folder("Editable"):
gui_vector2 = server.add_gui_vector2(
Expand Down Expand Up @@ -56,30 +57,31 @@ def main():
point_positions = onp.random.uniform(low=-1.0, high=1.0, size=(500, 3))
point_colors = onp.random.randint(0, 256, size=(500, 3))

frame_node = server.add_frame(
"/controlled_frame", wxyz=(1.0, 0.0, 0.0, 0.0), position=(0.0, 0.0, 0.0)
)

while True:
# We can call `set_value()` to set an input to a particular value.
gui_counter.set_value(counter)
gui_slider.set_value(counter % 100)

# We can call `value()` to read the current value of an input.
xy = gui_vector2.get_value()
server.add_frame(
"/controlled_frame",
wxyz=(1, 0, 0, 0),
position=xy + (0,),
)
# We can set the value of an input to a particular value. Changes are
# automatically reflected in connected clients.
gui_counter.value = counter
gui_slider.value = counter % 100

# We can set the position of a scene node with `.position`, and read the value
# of a gui element with `.value`. Changes are automatically reflected in
# connected clients.
frame_node.position = gui_vector2.value + (0,)

size = gui_vector3.get_value()
server.add_point_cloud(
"/controlled_frame/point_cloud",
position=point_positions * onp.array(size, dtype=onp.float32),
position=point_positions * onp.array(gui_vector3.value, dtype=onp.float32),
color=point_colors,
)

# We can use `set_disabled()` to enable/disable GUI elements.
gui_text.set_hidden(gui_checkbox_hide.get_value())
gui_button.set_hidden(gui_checkbox_hide.get_value())
gui_rgba.set_disabled(gui_checkbox_disable.get_value())
# We can use `.visible` and `.disabled` to toggle GUI elements.
gui_text.visible = not gui_checkbox_hide.value
gui_button.visible = not gui_checkbox_hide.value
gui_rgba.disabled = gui_checkbox_disable.value

counter += 1
time.sleep(1e-2)
Expand Down
24 changes: 11 additions & 13 deletions examples/5_gui_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ def main():

@gui_include_z.on_update
def _(_) -> None:
gui_axis.set_options(
["x", "y", "z"] if gui_include_z.get_value() else ["x", "y"]
)
gui_axis.options = ["x", "y", "z"] if gui_include_z.value else ["x", "y"]

with server.gui_folder("Sliders"):
gui_location = server.add_gui_slider(
Expand All @@ -42,26 +40,26 @@ def _(_) -> None:
gui_button = server.add_gui_button("Reset")

def draw_frame() -> None:
axis = gui_axis.get_value()
axis = gui_axis.value
if axis == "x":
pos = (gui_location.get_value(), 0.0, 0.0)
pos = (gui_location.value, 0.0, 0.0)
elif axis == "y":
pos = (0.0, gui_location.get_value(), 0.0)
pos = (0.0, gui_location.value, 0.0)
elif axis == "z":
pos = (0.0, 0.0, gui_location.get_value())
pos = (0.0, 0.0, gui_location.value)
else:
assert_never(axis)

server.add_frame(
"/frame",
wxyz=(1.0, 0.0, 0.0, 0.0),
position=pos,
show_axes=gui_show.get_value(),
show_axes=gui_show.value,
axes_length=5.0,
)

def draw_points() -> None:
num_points = gui_num_points.get_value()
num_points = gui_num_points.value
server.add_point_cloud(
"/frame/point_cloud",
position=onp.random.normal(size=(num_points, 3)),
Expand All @@ -78,10 +76,10 @@ def draw_points() -> None:
@gui_button.on_update
def _(_: viser.GuiHandle[bool]) -> None:
"""Reset the scene when the reset button is clicked."""
gui_show.set_value(True)
gui_location.set_value(0.0)
gui_axis.set_value("x")
gui_num_points.set_value(10_000)
gui_show.value = True
gui_location.value = 0.0
gui_axis.value = "x"
gui_num_points.value = 10_000

draw_frame()
draw_points()
Expand Down
Loading

0 comments on commit 419fac6

Please sign in to comment.