diff options
Diffstat (limited to 'src/SomhairlesDream.Frontend/App.fs')
| -rw-r--r-- | src/SomhairlesDream.Frontend/App.fs | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/src/SomhairlesDream.Frontend/App.fs b/src/SomhairlesDream.Frontend/App.fs index ec9e273..e6edd51 100644 --- a/src/SomhairlesDream.Frontend/App.fs +++ b/src/SomhairlesDream.Frontend/App.fs @@ -47,7 +47,14 @@ type ViewState = Scene: ThreeNode Camera: ThreeCamera Group: ThreeNode - Canvas: HTMLCanvasElement } + Canvas: HTMLCanvasElement + Controls: obj } + +// Auto-spin pauses while the visitor is dragging or zooming the model and +// resumes a few seconds after the last interaction, so inspecting a stage +// (dish, RTG, mast) is never fought by the idle animation. +let mutable lastInteractionMs = 0.0 +let idleSpinDelayMs = 3500.0 type LoadOwner = { ProjectId: string @@ -199,6 +206,14 @@ let frameObject (view: ViewState) (node: ThreeNode) = camera.lookAt(0.0, 0.0, 0.0) camera.updateProjectionMatrix () + // Re-sync the orbit target after every auto-fit so drag/zoom + // pivots around the freshly centered model. + match view.Controls with + | null -> () + | controls -> + setControlsTarget controls 0.0 0.0 0.0 + updateControls controls + let resizeView (view: ViewState) = let width = max 1.0 (float view.Canvas.clientWidth) let height = max 1.0 (float view.Canvas.clientHeight) @@ -230,7 +245,7 @@ let initializeView () = scene.background <- createColor("#11171a") let camera = createPerspectiveCamera(34.0, width / height, 0.1, 100.0) camera.position.set(6.4, 4.6, 7.2) |> ignore - camera.lookAt(0.0, 1.2, 0.0) + camera.lookAt(0.0, 0.0, 0.0) let group = createGroup() scene.add(group) scene.add(createAmbientLight("#f0e6c8", 1.9)) @@ -238,23 +253,40 @@ let initializeView () = keyLight.position.set(4.0, 7.0, 5.0) |> ignore scene.add(keyLight) + let controls = createOrbitControls camera canvas + setControlsTarget controls 0.0 0.0 0.0 + setControlsDamping controls true + setControlsAutoRotateSpeed controls 0.7 + let view = { Renderer = renderer Scene = scene Camera = camera Group = group - Canvas = canvas } + Canvas = canvas + Controls = controls } viewState <- Some view + freezeRotation <- (queryParam "freeze") = "1" - exposeViewerDebug camera scene group canvas + setControlsAutoRotate controls (not freezeRotation) + exposeViewerDebug camera scene group canvas controls renderFrame selectedFrame window.addEventListener("resize", fun _ -> resizeView view) - let rec animate (_: float) = + canvas.addEventListener("pointerdown", fun _ -> lastInteractionMs <- JS.Constructors.Date.now ()) + canvas.addEventListener("wheel", fun _ -> lastInteractionMs <- JS.Constructors.Date.now ()) + canvas.addEventListener("touchstart", fun _ -> lastInteractionMs <- JS.Constructors.Date.now ()) + + let rec animate (nowMs: float) = + updateControls controls + if not freezeRotation then group.rotation.y <- group.rotation.y + 0.003 + let interacting = nowMs - lastInteractionMs < idleSpinDelayMs + setControlsAutoRotate controls (not freezeRotation && not interacting) + renderer.render(scene, camera) requestAnimationFrame animate |> ignore |
