Skip to content

Commit

Permalink
feat(itk-camera): send full camera pose
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulHax committed Aug 3, 2023
1 parent 167df42 commit 0cb3814
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 16 deletions.
51 changes: 43 additions & 8 deletions packages/element/src/itk-camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { ReadonlyMat4, mat4 } from 'gl-matrix';
import createOrbitCamera from 'orbit-camera';

import { Viewport } from '@itk-viewer/viewer/viewport.js';
import { createCamera } from '@itk-viewer/viewer/camera-machine.js';
import { Camera, createCamera } from '@itk-viewer/viewer/camera-machine.js';
import { Ref, createRef, ref } from 'lit/directives/ref.js';

type OrbitCameraController = ReturnType<typeof createOrbitCamera>;

const PAN_SPEED = 1;
const ZOOM_SPEED = 0.005;

const bindCamera = (
camera: OrbitCameraController,
Expand All @@ -21,6 +22,12 @@ const bindCamera = (

const view = mat4.create();

const updateView = () => {
camera.view(view);
mat4.invert(view, view);
onUpdate(view);
};

const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
width = entry.contentRect.width;
Expand All @@ -42,17 +49,20 @@ const bindCamera = (
} else if (e.button === 2) {
pan = true;
}
return false;
};
element.addEventListener('mousedown', onMouseDown);

const onMouseUp = (e: MouseEvent) => {
e.preventDefault();
if (e.button === 0) {
rotate = false;
} else if (e.button === 1) {
scale = false;
} else if (e.button === 2) {
pan = false;
}
return false;
};
element.addEventListener('mouseup', onMouseUp);

Expand Down Expand Up @@ -86,16 +96,29 @@ const bindCamera = (
prevMouseY = mouseY;

if (!rotate && !pan && !scale) return;
camera.view(view);
onUpdate(view);

updateView();
};
element.addEventListener('mousemove', onMouseMove);

const onWheel = (e: WheelEvent) => {
e.preventDefault();
camera.zoom(e.deltaY * ZOOM_SPEED);

updateView();
};
element.addEventListener('wheel', onWheel, { passive: false });

const preventDefault = (e: Event) => e.preventDefault();
element.addEventListener('contextmenu', preventDefault);

const unbind = () => {
resizeObserver.disconnect();
element.removeEventListener('mousemove', onMouseMove);
element.removeEventListener('mousedown', onMouseDown);
element.removeEventListener('mouseup', onMouseUp);
element.removeEventListener('wheel', onWheel);
element.removeEventListener('contextmenu', preventDefault);
};

return unbind;
Expand All @@ -106,24 +129,36 @@ export class ItkCamera extends LitElement {
@property({ attribute: false })
viewport: Viewport | undefined;

camera = createCamera();
camera: Camera;
cameraController: OrbitCameraController;
unbind: (() => unknown) | undefined;
container: Ref<HTMLElement> = createRef();

firstUpdated(): void {
const cameraController = createOrbitCamera(
constructor() {
super();
this.camera = createCamera();

this.cameraController = createOrbitCamera(
[-0.747528, -0.570641, 0.754992],
[0.5, 0.5, 0.5],
[-0.505762, 0.408327, -0.759916]
);

const pose = this.cameraController.view();
this.camera.send({
type: 'setPose',
pose,
});
}

firstUpdated(): void {
const container = this.container.value;
if (!container) throw new Error('container not found');

this.unbind = bindCamera(cameraController, container, (view) => {
this.unbind = bindCamera(this.cameraController, container, (pose) => {
this.camera.send({
type: 'setPose',
pose: view,
pose,
});
});
}
Expand Down
15 changes: 9 additions & 6 deletions packages/remote-viewport/src/remote-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const remoteMachine = createMachine({
disconnected: {
entry: ({ context, self }) => {
// Update camera pose on viewport change
// FIXME: not capturing initial camera position because updateRender handler not registered before connection
context.viewport.subscribe(() => {
const cameraPose = context.viewport
.getSnapshot()
Expand Down Expand Up @@ -98,8 +99,8 @@ export const remoteMachine = createMachine({
actions: assign({
server: ({ event }) => event.output,
// initially, send all props to renderer
queuedRendererEvents: ({ context }) =>
getEntries(context.rendererProps),
// queuedRendererEvents: ({ context }) =>
// getEntries(context.rendererProps),
}),
target: 'online',
},
Expand All @@ -110,10 +111,12 @@ export const remoteMachine = createMachine({
updateRenderer: {
actions: [
assign({
rendererProps: ({ event: { props }, context }) => ({
...context.rendererProps,
...props,
}),
rendererProps: ({ event: { props }, context }) => {
return {
...context.rendererProps,
...props,
};
},
queuedRendererEvents: ({ event: { props }, context }) => [
...context.queuedRendererEvents,
...(getEntries(props) as RendererEntries),
Expand Down
10 changes: 8 additions & 2 deletions packages/remote-viewport/src/remote-viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const createHyphaRenderer = async (server_url: string) => {
server_url,
};
const server = await hyphaWebsocketClient.connectToServer(config);
const renderer = await server.getService('test-agave-renderer-paul');
const renderer = await server.getService('test-agave-renderer');
await renderer.setup();
await renderer.setImage('data/aneurism.ome.tif');
return renderer;
Expand All @@ -42,7 +42,13 @@ export const createHyphaActors: () => RemoteMachineActors = () => ({
if (key === 'cameraPose') {
const eye = vec3.create();
mat4.getTranslation(eye, value);
return ['cameraPose', { eye }];

const target = vec3.fromValues(value[8], value[9], value[10]);
vec3.subtract(target, eye, target);

const up = vec3.fromValues(value[4], value[5], value[6]);

return ['cameraPose', { eye, up, target }];
}
return [key, value];
});
Expand Down

0 comments on commit 0cb3814

Please sign in to comment.