diff --git a/packages/element/src/itk-camera.ts b/packages/element/src/itk-camera.ts index 3266af51..0fee80de 100644 --- a/packages/element/src/itk-camera.ts +++ b/packages/element/src/itk-camera.ts @@ -4,7 +4,7 @@ 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; @@ -42,10 +42,12 @@ 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) { @@ -53,6 +55,7 @@ const bindCamera = ( } else if (e.button === 2) { pan = false; } + return false; }; element.addEventListener('mouseup', onMouseUp); @@ -86,16 +89,23 @@ const bindCamera = ( prevMouseY = mouseY; if (!rotate && !pan && !scale) return; + camera.view(view); + mat4.invert(view, view); + onUpdate(view); }; element.addEventListener('mousemove', onMouseMove); + 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('contextmenu', preventDefault); }; return unbind; @@ -106,24 +116,39 @@ export class ItkCamera extends LitElement { @property({ attribute: false }) viewport: Viewport | undefined; - camera = createCamera(); + camera: Camera; + cameraController: OrbitCameraController; unbind: (() => unknown) | undefined; container: Ref = createRef(); - firstUpdated(): void { - const cameraController = createOrbitCamera( - [-0.747528, -0.570641, 0.754992], - [0.5, 0.5, 0.5], - [-0.505762, 0.408327, -0.759916] + 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] + [0, 0, 1], + [0, 0, 0], + [0, 1, 0] ); + 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, }); }); } diff --git a/packages/remote-viewport/src/remote-machine.ts b/packages/remote-viewport/src/remote-machine.ts index a77f44a5..c0d1e5a0 100644 --- a/packages/remote-viewport/src/remote-machine.ts +++ b/packages/remote-viewport/src/remote-machine.ts @@ -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() @@ -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', }, @@ -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), diff --git a/packages/remote-viewport/src/remote-viewport.ts b/packages/remote-viewport/src/remote-viewport.ts index 353ad4c1..0f913436 100644 --- a/packages/remote-viewport/src/remote-viewport.ts +++ b/packages/remote-viewport/src/remote-viewport.ts @@ -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; @@ -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]; });