Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add .near and .far props to camera handles #356

Merged
merged 2 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/source/examples/05_camera_commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,29 @@ corresponding client automatically.
num_frames = 20


@server.on_client_connect
def _(client: viser.ClientHandle) -> None:
"""For each client that connects, create GUI elements for adjusting the
near/far clipping planes."""

client.camera.far = 10.0

near_slider = client.gui.add_slider(
"Near", min=0.01, max=10.0, step=0.001, initial_value=client.camera.near
)
far_slider = client.gui.add_slider(
"Far", min=1, max=20.0, step=0.001, initial_value=client.camera.far
)

@near_slider.on_update
def _(_) -> None:
client.camera.near = near_slider.value

@far_slider.on_update
def _(_) -> None:
client.camera.far = far_slider.value


@server.on_client_connect
def _(client: viser.ClientHandle) -> None:
"""For each client that connects, we create a set of random frames + a click handler for each frame.
Expand Down
23 changes: 23 additions & 0 deletions examples/05_camera_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,29 @@
num_frames = 20


@server.on_client_connect
def _(client: viser.ClientHandle) -> None:
"""For each client that connects, create GUI elements for adjusting the
near/far clipping planes."""

client.camera.far = 10.0

near_slider = client.gui.add_slider(
"Near", min=0.01, max=10.0, step=0.001, initial_value=client.camera.near
)
far_slider = client.gui.add_slider(
"Far", min=1, max=20.0, step=0.001, initial_value=client.camera.far
)

@near_slider.on_update
def _(_) -> None:
client.camera.near = near_slider.value

@far_slider.on_update
def _(_) -> None:
client.camera.far = far_slider.value


@server.on_client_connect
def _(client: viser.ClientHandle) -> None:
"""For each client that connects, we create a set of random frames + a click handler for each frame.
Expand Down
16 changes: 16 additions & 0 deletions src/viser/_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ class ViewerCameraMessage(Message):
wxyz: Tuple[float, float, float, float]
position: Tuple[float, float, float]
fov: float
near: float
far: float
aspect: float
look_at: Tuple[float, float, float]
up_direction: Tuple[float, float, float]
Expand Down Expand Up @@ -701,6 +703,20 @@ class SetCameraLookAtMessage(Message):
look_at: Tuple[float, float, float]


@dataclasses.dataclass
class SetCameraNearMessage(Message):
"""Server -> client message to set the camera's near clipping plane."""

near: float


@dataclasses.dataclass
class SetCameraFarMessage(Message):
"""Server -> client message to set the camera's far clipping plane."""

far: float


@dataclasses.dataclass
class SetCameraFovMessage(Message):
"""Server -> client message to set the camera's field of view."""
Expand Down
50 changes: 45 additions & 5 deletions src/viser/_viser.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class _CameraHandleState:
position: npt.NDArray[np.float64]
fov: float
aspect: float
near: float
far: float
look_at: npt.NDArray[np.float64]
up_direction: npt.NDArray[np.float64]
update_timestamp: float
Expand All @@ -92,6 +94,8 @@ def __init__(self, client: ClientHandle) -> None:
position=np.zeros(3),
fov=0.0,
aspect=0.0,
near=0.01,
far=1000.0,
look_at=np.zeros(3),
up_direction=np.zeros(3),
update_timestamp=0.0,
Expand Down Expand Up @@ -204,6 +208,40 @@ def fov(self, fov: float) -> None:
_messages.SetCameraFovMessage(fov)
)

@property
def near(self) -> float:
"""Near clipping plane distance. Synchronized automatically when
assigned."""
assert self._state.update_timestamp != 0.0
return self._state.near

@near.setter
def near(self, near: float) -> None:
if np.allclose(self._state.near, near):
return
self._state.near = near
self._state.update_timestamp = time.time()
self._state.client._websock_connection.queue_message(
_messages.SetCameraNearMessage(near)
)

@property
def far(self) -> float:
"""Far clipping plane distance. Synchronized automatically when
assigned."""
assert self._state.update_timestamp != 0.0
return self._state.far

@far.setter
def far(self, far: float) -> None:
if np.allclose(self._state.far, far):
return
self._state.far = far
self._state.update_timestamp = time.time()
self._state.client._websock_connection.queue_message(
_messages.SetCameraFarMessage(far)
)

@property
def aspect(self) -> float:
"""Canvas width divided by height. Not assignable."""
Expand Down Expand Up @@ -599,11 +637,13 @@ async def handle_camera_message(
client,
np.array(message.wxyz),
np.array(message.position),
message.fov,
message.aspect,
np.array(message.look_at),
np.array(message.up_direction),
time.time(),
fov=message.fov,
aspect=message.aspect,
near=message.near,
far=message.far,
look_at=np.array(message.look_at),
up_direction=np.array(message.up_direction),
update_timestamp=time.time(),
camera_cb=client.camera._state.camera_cb,
)

Expand Down
5 changes: 3 additions & 2 deletions src/viser/client/src/CameraControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export function SynchronizedCameraControls() {
position: t_world_camera.toArray(),
aspect: three_camera.aspect,
fov: (three_camera.fov * Math.PI) / 180.0,
near: three_camera.near,
far: three_camera.far,
look_at: [lookAt.x, lookAt.y, lookAt.z],
up_direction: [up.x, up.y, up.z],
});
Expand Down Expand Up @@ -247,8 +249,7 @@ export function SynchronizedCameraControls() {
return (
<CameraControls
ref={viewer.cameraControlRef}
minDistance={0.1}
maxDistance={200.0}
minDistance={0.01}
dollySpeed={0.3}
smoothTime={0.05}
draggingSmoothTime={0.0}
Expand Down
12 changes: 12 additions & 0 deletions src/viser/client/src/MessageHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,18 @@ function useMessageHandler() {
viewer.sendCameraRef.current !== null && viewer.sendCameraRef.current();
return;
}
case "SetCameraNearMessage": {
const camera = viewer.cameraRef.current!;
camera.near = message.near;
camera.updateProjectionMatrix();
return;
}
case "SetCameraFarMessage": {
const camera = viewer.cameraRef.current!;
camera.far = message.far;
camera.updateProjectionMatrix();
return;
}
case "SetOrientationMessage": {
const attr = viewer.nodeAttributesFromName.current;
if (attr[message.name] === undefined) attr[message.name] = {};
Expand Down
20 changes: 20 additions & 0 deletions src/viser/client/src/WebsocketMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,8 @@ export interface ViewerCameraMessage {
wxyz: [number, number, number, number];
position: [number, number, number];
fov: number;
near: number;
far: number;
aspect: number;
look_at: [number, number, number];
up_direction: [number, number, number];
Expand Down Expand Up @@ -889,6 +891,22 @@ export interface SetCameraLookAtMessage {
type: "SetCameraLookAtMessage";
look_at: [number, number, number];
}
/** Server -> client message to set the camera's near clipping plane.
*
* (automatically generated)
*/
export interface SetCameraNearMessage {
type: "SetCameraNearMessage";
near: number;
}
/** Server -> client message to set the camera's far clipping plane.
*
* (automatically generated)
*/
export interface SetCameraFarMessage {
type: "SetCameraFarMessage";
far: number;
}
/** Server -> client message to set the camera's field of view.
*
* (automatically generated)
Expand Down Expand Up @@ -1201,6 +1219,8 @@ export type Message =
| SetCameraPositionMessage
| SetCameraUpDirectionMessage
| SetCameraLookAtMessage
| SetCameraNearMessage
| SetCameraFarMessage
| SetCameraFovMessage
| SetOrientationMessage
| SetPositionMessage
Expand Down
Loading