summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-05-02 02:11:37 -0400
committerJoe Crayne <joe@jerkface.net>2019-05-02 02:11:37 -0400
commit7853a4b2f025d6368564bc9ea6cbf72c36b6fcd9 (patch)
treebf64e077d14fbba3a44cd1e6d3ce37dbd25a287a
parenta7998a03dccd5c879508e729559de20743c7dafd (diff)
meshsketch: drag background.
-rw-r--r--MeshSketch.hs127
1 files changed, 121 insertions, 6 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs
index 6d7e757..c88da0c 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -53,6 +53,7 @@ data State = State
53 , stSkyboxes :: Skyboxes 53 , stSkyboxes :: Skyboxes
54 , stSkybox :: IORef Int 54 , stSkybox :: IORef Int
55 , stSkyTexture :: IORef TextureData 55 , stSkyTexture :: IORef TextureData
56 , stDragFrom :: IORef (Maybe (Vector Float,Camera))
56 } 57 }
57 58
58data Camera = Camera 59data Camera = Camera
@@ -140,6 +141,8 @@ uploadState obj glarea storage = do
140 mi <- LC.uploadMeshToGPU cubeMesh 141 mi <- LC.uploadMeshToGPU cubeMesh
141 LC.addMeshToObjectArray storage "SkyCube" [] mi 142 LC.addMeshToObjectArray storage "SkyCube" [] mi
142 143
144 drag <- newIORef Nothing
145
143 let st = State 146 let st = State
144 { stAnimator = tm 147 { stAnimator = tm
145 , stCamera = cam 148 , stCamera = cam
@@ -147,8 +150,9 @@ uploadState obj glarea storage = do
147 , stSkyboxes = skyboxes 150 , stSkyboxes = skyboxes
148 , stSkybox = skybox 151 , stSkybox = skybox
149 , stSkyTexture = skytex 152 , stSkyTexture = skytex
153 , stDragFrom = drag
150 } 154 }
151 _ <- addAnimation tm (whirlingCamera st) 155 -- _ <- addAnimation tm (whirlingCamera st)
152 156
153 return st 157 return st
154 158
@@ -164,7 +168,7 @@ deg30 = pi/6
164whirlingCamera :: State -> Animation 168whirlingCamera :: State -> Animation
165whirlingCamera st = Animation $ \_ t -> do 169whirlingCamera st = Animation $ \_ t -> do
166 let tf = realToFrac t :: Float 170 let tf = realToFrac t :: Float
167 rot = rotMatrixZ (-tf) <> rotMatrixX (-tf) 171 rot = rotMatrixZ (-tf/2) <> rotMatrixX (-tf/pi)
168 modifyIORef (stCamera st) $ \cam -> cam 172 modifyIORef (stCamera st) $ \cam -> cam
169 { camUp = rot #> fromList [0,1,0] 173 { camUp = rot #> fromList [0,1,0]
170 , camDirection = (scale (1/camDistance cam) $ fromList [-2,-2,-10]) <# rot 174 , camDirection = (scale (1/camDistance cam) $ fromList [-2,-2,-10]) <# rot
@@ -285,10 +289,79 @@ onResize glarea realized w h = do
285 modifyIORef' (stCamera $ stState realized) 289 modifyIORef' (stCamera $ stState realized)
286 $ \c -> c { camWidth = fromIntegral wd 290 $ \c -> c { camWidth = fromIntegral wd
287 , camHeight = fromIntegral ht 291 , camHeight = fromIntegral ht
292 , camWorldToScreen = Nothing
293 , camScreenToWorld = Nothing
288 } 294 }
289 LC.setScreenSize (stStorage realized) wd ht) 295 LC.setScreenSize (stStorage realized) wd ht)
290 296
291onEvent :: w -> Realized -> Event -> IO Bool 297computeDirection :: Camera -> Double -> Double -> Vector Float
298computeDirection cam h k =
299 let d̂ = camDirection cam -- forward
300 û = camUp cam -- upward
301 r̂ = d̂ `cross` û -- rightward
302 xr = realToFrac h - (camWidth cam / 2)
303 xu = (camHeight cam / 2) - realToFrac k
304 xd = (camHeight cam / 2) / tan (camHeightAngle cam / 2)
305 in scale xr r̂ + scale xu û + scale xd d̂
306
307rotate :: Float -> Vector Float -> Matrix Float
308rotate cosθ u = (3><3)
309 [ cosθ + ux² mcosθ , (uy.uy)mcosθ - uz sinθ , (ux.uz)mcosθ + uy sinθ
310 , (uy.ux)mcosθ + uz sinθ , cosθ + uy² mcosθ , (uy.uz)mcosθ - ux sinθ
311 , (uz.ux)mcosθ - uy sinθ , (uz.uy)mcosθ + ux sinθ , cosθ + uz² mcosθ
312 ]
313 where
314 sinθ = sqrt (1 - cosθ * cosθ)
315 mcosθ = 1 - cosθ
316 û = scale (1/realToFrac (norm_2 u)) u
317 ux a = (û!0) * a
318 uy a = (û!1) * a
319 uz a = (û!2) * a
320 ux² = ux . ux
321 uy² = uy . uy
322 uz² = uz . uz
323
324updateCameraRotation w st h k = do
325 m <- readIORef (stDragFrom st)
326 forM_ m $ \(df,cam) -> do
327 let d̂ = camDirection cam -- forward
328 û = camUp cam -- upward
329 r̂ = d̂ `cross` û -- rightward
330 -- fr = df `dot` r̂
331 -- fu = df `dot` û
332 -- fd = df `dot` d̂
333 dt = computeDirection cam h k
334 -- tr = dt `dot` r̂
335 -- tu = dt `dot` û
336 -- td = dt `dot` d̂
337 cosθ = dot df dt / realToFrac (norm_2 df) / realToFrac (norm_2 dt)
338 axis = df `cross` dt
339 cam' = cam
340 { camDirection = d̂ <# rotate cosθ axis
341 , camWorldToScreen = Nothing
342 , camScreenToWorld = Nothing
343 }
344 writeIORef (stCamera st) cam'
345 mwin <- widgetGetWindow w
346 forM_ mwin $ \win ->
347 windowInvalidateRect win Nothing False
348
349sanitizeCamera st = do
350 modifyIORef (stCamera st) $ \cam ->
351 let d = camDirection cam
352 dd = norm_2 d
353 e = scale (realToFrac $ 1/dd) d
354 d̂ = if any isNaN (toList e)
355 then fromList [0,0,-1]
356 else e
357 in cam
358 { camDirection = d̂
359 , camWorldToScreen = Nothing
360 , camScreenToWorld = Nothing
361 }
362
363
364onEvent :: IsWidget w => w -> Realized -> Event -> IO Bool
292onEvent w realized ev = do 365onEvent w realized ev = do
293 let st = stState realized 366 let st = stState realized
294 msrc <- eventGetSourceDevice ev 367 msrc <- eventGetSourceDevice ev
@@ -298,15 +371,54 @@ onEvent w realized ev = do
298 etype <- get ev #type 371 etype <- get ev #type
299 -- putStrLn $ "onEvent! " ++ show (etype,inputSource) 372 -- putStrLn $ "onEvent! " ++ show (etype,inputSource)
300 let put x = putStrLn (show inputSource ++ " " ++ show x) 373 let put x = putStrLn (show inputSource ++ " " ++ show x)
374 let st = stState realized
301 case etype of 375 case etype of
302 376
303 EventTypeMotionNotify -> do 377 EventTypeMotionNotify -> do
304 mev <- get ev #motion 378 mev <- get ev #motion
305 x <- get mev #x 379 h <- get mev #x
306 y <- get mev #y 380 k <- get mev #y
307 put (x,y) 381 {-
382 cam <- readIORef (stCamera st)
383 {-
384 let o = fromList [ camWidth cam / 2, camHeight cam / 2 ]
385 r = camHeight cam / (2 * sin (camHeight cam / 2))
386
387 c = fromList [realToFrac h, realToFrac k] - o :: Vector Float
388 d = realToFrac $ norm_2 c
389 τ = asin (d / r) -- angle from center
390 axis = fromList [c!1, - (c!0)] :: Vector Float
391 -}
392 let d̂ = camDirection cam -- forward
393 û = camUp cam -- upward
394 r̂ = d̂ `cross` û -- rightward
395 x_r = realToFrac h - (camWidth cam / 2)
396 x_u = (camHeight cam / 2) - realToFrac k
397 x_d = (camHeight cam / 2) / tan (camHeightAngle cam / 2)
398 x = fromList [x_r,x_u,x_d]
399 -}
400
401 updateCameraRotation w st h k
308 return () 402 return ()
309 403
404 EventTypeButtonPress -> do
405 bev <- get ev #button
406 h <- get bev #x
407 k <- get bev #y
408 cam <- readIORef (stCamera st)
409 let d = computeDirection cam h k
410 writeIORef (stDragFrom st) $ Just (d,cam)
411 put (etype,(h,k),d)
412 return ()
413
414 EventTypeButtonRelease -> do
415 bev <- get ev #button
416 h <- get bev #x
417 k <- get bev #y
418 updateCameraRotation w st h k
419 sanitizeCamera st
420 writeIORef (stDragFrom st) Nothing
421
310 EventTypeScroll -> do 422 EventTypeScroll -> do
311 sev <- get ev #scroll 423 sev <- get ev #scroll
312 d <- get sev #direction 424 d <- get sev #direction
@@ -320,6 +432,9 @@ onEvent w realized ev = do
320 , camWorldToScreen = Nothing 432 , camWorldToScreen = Nothing
321 , camScreenToWorld = Nothing 433 , camScreenToWorld = Nothing
322 } 434 }
435 mwin <- widgetGetWindow w
436 forM_ mwin $ \win ->
437 windowInvalidateRect win Nothing False
323 put d 438 put d
324 return () 439 return ()
325 440