Skip to content

Commit

Permalink
Grid support (#116)
Browse files Browse the repository at this point in the history
* Add grid message

* Add plane parameterization comment
  • Loading branch information
brentyi authored Oct 18, 2023
1 parent e1cd20e commit e51df26
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 3 deletions.
17 changes: 17 additions & 0 deletions examples/03_gui_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ def main() -> None:

gui_reset_scene = server.add_gui_button("Reset Scene")

gui_plane = server.add_gui_dropdown(
"Grid plane", ("xz", "xy", "yx", "yz", "zx", "zy")
)

def update_plane() -> None:
server.add_grid(
"/grid",
width=10.0,
height=20.0,
width_segments=10,
height_segments=20,
plane=gui_plane.value,
)

gui_plane.on_update(lambda _: update_plane())

with server.add_gui_folder("Control"):
gui_show = server.add_gui_checkbox("Show Frame", initial_value=True)
gui_axis = server.add_gui_dropdown("Axis", ("x", "y", "z"))
Expand Down Expand Up @@ -83,6 +99,7 @@ def _(_) -> None:
draw_points()

# Finally, let's add the initial frame + point cloud and just loop infinitely. :)
update_plane()
draw_frame()
draw_points()
while True:
Expand Down
40 changes: 38 additions & 2 deletions src/viser/_message_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,7 @@ def add_frame(
position: Tuple[float, float, float] | onp.ndarray = (0.0, 0.0, 0.0),
visible: bool = True,
) -> FrameHandle:
cast_vector(wxyz, length=4)
cast_vector(position, length=3)
"""Add a coordinate frame to the scene."""
self._queue(
_messages.FrameMessage(
name=name,
Expand All @@ -366,6 +365,43 @@ def add_frame(
)
return FrameHandle._make(self, name, wxyz, position, visible)

def add_grid(
self,
name: str,
width: float = 10.0,
height: float = 10.0,
width_segments: int = 10,
height_segments: int = 10,
plane: Literal["xz", "xy", "yx", "yz", "zx", "zy"] = "xy",
cell_color: RgbTupleOrArray = (200, 200, 200),
cell_thickness: float = 1.0,
cell_size: float = 0.5,
section_color: RgbTupleOrArray = (140, 140, 140),
section_thickness: float = 1.0,
section_size: float = 1.0,
wxyz: Tuple[float, float, float, float] | onp.ndarray = (1.0, 0.0, 0.0, 0.0),
position: Tuple[float, float, float] | onp.ndarray = (0.0, 0.0, 0.0),
visible: bool = True,
) -> MeshHandle:
"""Add a grid to the scene. Useful for visualizing things like ground planes."""
self._queue(
_messages.GridMessage(
name=name,
width=width,
height=height,
width_segments=width_segments,
height_segments=height_segments,
plane=plane,
cell_color=_encode_rgb(cell_color),
cell_thickness=cell_thickness,
cell_size=cell_size,
section_color=_encode_rgb(section_color),
section_thickness=section_thickness,
section_size=section_size,
)
)
return MeshHandle._make(self, name, wxyz, position, visible)

def add_label(
self,
name: str,
Expand Down
22 changes: 22 additions & 0 deletions src/viser/_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,28 @@ class FrameMessage(Message):
axes_radius: float = 0.025


@dataclasses.dataclass
class GridMessage(Message):
"""Grid message. Helpful for visualizing things like ground planes."""

name: str

width: float
height: float
width_segments: int
height_segments: int

plane: Literal["xz", "xy", "yx", "yz", "zx", "zy"]

cell_color: int
cell_thickness: float
cell_size: float

section_color: int
section_thickness: float
section_size: float


@dataclasses.dataclass
class LabelMessage(Message):
"""Add a 2D label to the scene."""
Expand Down
53 changes: 52 additions & 1 deletion src/viser/client/src/WebsocketInterface.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AwaitLock from "await-lock";
import { CatmullRomLine, CubicBezierLine } from "@react-three/drei";
import { CatmullRomLine, CubicBezierLine, Grid } from "@react-three/drei";
import { unpack } from "msgpackr";

import React, { useContext } from "react";
Expand Down Expand Up @@ -120,6 +120,57 @@ function useMessageHandler() {
return;
}

case "GridMessage": {
addSceneNodeMakeParents(
new SceneNode<THREE.Group>(message.name, (ref) => (
<group ref={ref}>
<Grid
args={[
message.width,
message.height,
message.width_segments,
message.height_segments,
]}
side={THREE.DoubleSide}
cellColor={message.cell_color}
cellThickness={message.cell_thickness}
cellSize={message.cell_size}
sectionColor={message.section_color}
sectionThickness={message.section_thickness}
sectionSize={message.section_size}
rotation={
// There's redundancy here when we set the side to
// THREE.DoubleSide, where xy and yx should be the same.
//
// But it makes sense to keep this parameterization because
// specifying planes by xy seems more natural than the normal
// direction (z, +z, or -z), and it opens the possibility of
// rendering only FrontSide or BackSide grids in the future.
//
// If we add support for FrontSide or BackSide, we should
// double-check that the normal directions from each of these
// rotations match the right-hand rule!
message.plane == "xz"
? new THREE.Euler(0.0, 0.0, 0.0)
: message.plane == "xy"
? new THREE.Euler(Math.PI / 2.0, 0.0, 0.0)
: message.plane == "yx"
? new THREE.Euler(0.0, Math.PI / 2.0, Math.PI / 2.0)
: message.plane == "yz"
? new THREE.Euler(0.0, 0.0, Math.PI / 2.0)
: message.plane == "zx"
? new THREE.Euler(0.0, Math.PI / 2.0, 0.0)
: message.plane == "zy"
? new THREE.Euler(-Math.PI / 2.0, 0.0, -Math.PI / 2.0)
: undefined
}
/>
</group>
)),
);
return;
}

// Add a point cloud.
case "PointCloudMessage": {
const geometry = new THREE.BufferGeometry();
Expand Down
20 changes: 20 additions & 0 deletions src/viser/client/src/WebsocketMessages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,25 @@ export interface FrameMessage {
axes_length: number;
axes_radius: number;
}
/** Grid message. Helpful for visualizing things like ground planes.
*
* (automatically generated)
*/
export interface GridMessage {
type: "GridMessage";
name: string;
width: number;
height: number;
width_segments: number;
height_segments: number;
plane: "xz" | "xy" | "yx" | "yz" | "zx" | "zy";
cell_color: number;
cell_thickness: number;
cell_size: number;
section_color: number;
section_thickness: number;
section_size: number;
}
/** Add a 2D label to the scene.
*
* (automatically generated)
Expand Down Expand Up @@ -657,6 +676,7 @@ export type Message =
| CameraFrustumMessage
| GlbMessage
| FrameMessage
| GridMessage
| LabelMessage
| Gui3DMessage
| PointCloudMessage
Expand Down

0 comments on commit e51df26

Please sign in to comment.