summaryrefslogtreecommitdiff
path: root/src/SomhairlesDream.Frontend/App.fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SomhairlesDream.Frontend/App.fs')
-rw-r--r--src/SomhairlesDream.Frontend/App.fs42
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