diff options
author | Joe Crayne <joe@jerkface.net> | 2019-05-18 16:14:09 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-05-18 16:14:09 -0400 |
commit | 7b366a9d7e80ff7d9847eafb7a47fba06faac40e (patch) | |
tree | abdcd558be20c4fa656367d538e8bf11d59b2cc4 | |
parent | a590439eef76c5fe1e8ec7fce28a3b194bfd6e8e (diff) |
Control to move draw-plane up and down.
-rw-r--r-- | MeshSketch.hs | 81 |
1 files changed, 62 insertions, 19 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs index 14039e9..5ada40e 100644 --- a/MeshSketch.hs +++ b/MeshSketch.hs | |||
@@ -17,7 +17,7 @@ import Data.Text (Text) | |||
17 | import Data.Map.Strict (Map) | 17 | import Data.Map.Strict (Map) |
18 | import qualified Data.Map.Strict as Map | 18 | import qualified Data.Map.Strict as Map |
19 | import qualified Data.Vector as V | 19 | import qualified Data.Vector as V |
20 | import qualified Data.Vector.Generic as G (init,(//)) | 20 | import qualified Data.Vector.Generic as G |
21 | import Foreign.Marshal.Array | 21 | import Foreign.Marshal.Array |
22 | import Foreign.Storable | 22 | import Foreign.Storable |
23 | import GI.Gdk | 23 | import GI.Gdk |
@@ -72,6 +72,7 @@ setupGLDebugging = do | |||
72 | GL.debugMessageControl (GL.MessageGroup Nothing Nothing Nothing) GL.$= GL.Enabled | 72 | GL.debugMessageControl (GL.MessageGroup Nothing Nothing Nothing) GL.$= GL.Enabled |
73 | GL.debugMessageCallback GL.$= Just pdebug | 73 | GL.debugMessageCallback GL.$= Just pdebug |
74 | 74 | ||
75 | type Plane = Vector Float | ||
75 | 76 | ||
76 | -- State created by uploadState. | 77 | -- State created by uploadState. |
77 | data State = State | 78 | data State = State |
@@ -84,7 +85,8 @@ data State = State | |||
84 | , stDragFrom :: IORef (Maybe (Vector Float,Camera)) | 85 | , stDragFrom :: IORef (Maybe (Vector Float,Camera)) |
85 | , stRingBuffer :: Ring | 86 | , stRingBuffer :: Ring |
86 | , stPenDown :: IORef Bool | 87 | , stPenDown :: IORef Bool |
87 | , stPlane :: IORef (Maybe (Vector Float)) | 88 | , stPlane :: IORef (Maybe Plane) |
89 | , stDragPlane :: IORef (Maybe (Vector Float,Plane)) | ||
88 | } | 90 | } |
89 | 91 | ||
90 | data Camera = Camera | 92 | data Camera = Camera |
@@ -206,6 +208,7 @@ uploadState obj glarea storage = do | |||
206 | LC.addMeshToObjectArray storage "SkyCube" [] mi | 208 | LC.addMeshToObjectArray storage "SkyCube" [] mi |
207 | 209 | ||
208 | drag <- newIORef Nothing | 210 | drag <- newIORef Nothing |
211 | dragPlane <- newIORef Nothing | ||
209 | pendown <- newIORef False | 212 | pendown <- newIORef False |
210 | plane <- newIORef $ Just (xzPlaneVector G.// [(3,-1)]) | 213 | plane <- newIORef $ Just (xzPlaneVector G.// [(3,-1)]) |
211 | 214 | ||
@@ -220,6 +223,7 @@ uploadState obj glarea storage = do | |||
220 | , stRingBuffer = ring | 223 | , stRingBuffer = ring |
221 | , stPenDown = pendown | 224 | , stPenDown = pendown |
222 | , stPlane = plane | 225 | , stPlane = plane |
226 | , stDragPlane = dragPlane | ||
223 | } | 227 | } |
224 | -- _ <- addAnimation tm (whirlingCamera st) | 228 | -- _ <- addAnimation tm (whirlingCamera st) |
225 | 229 | ||
@@ -388,6 +392,9 @@ onResize glarea realized w h = do | |||
388 | } | 392 | } |
389 | LC.setScreenSize (stStorage realized) wd ht | 393 | LC.setScreenSize (stStorage realized) wd ht |
390 | 394 | ||
395 | unit :: (Linear t c, Fractional t, Normed (c t)) => c t -> c t | ||
396 | unit v = scale (1/realToFrac (norm_2 v)) v | ||
397 | |||
391 | -- This computes a point in world coordinates on the view screen if | 398 | -- This computes a point in world coordinates on the view screen if |
392 | -- we assume the camera is located at the origin. | 399 | -- we assume the camera is located at the origin. |
393 | computeDirection :: Camera -> Double -> Double -> Vector Float | 400 | computeDirection :: Camera -> Double -> Double -> Vector Float |
@@ -399,9 +406,11 @@ computeDirection cam h k | Just pv <- camScreenToWorld cam = | |||
399 | ] :: Vector Float | 406 | ] :: Vector Float |
400 | d1 = pv #> d0 | 407 | d1 = pv #> d0 |
401 | d2 = scale (1 /(d1!3)) $ G.init d1 | 408 | d2 = scale (1 /(d1!3)) $ G.init d1 |
409 | {- | ||
402 | p = camPos cam | 410 | p = camPos cam |
403 | d3 = d2 - p | 411 | d3 = d2 - p |
404 | d4 = scale (1/realToFrac (norm_2 d3)) d3 | 412 | d4 = unit d3 |
413 | -} | ||
405 | in d2 | 414 | in d2 |
406 | computeDirection cam h k = | 415 | computeDirection cam h k = |
407 | let d̂ = camDirection cam -- forward | 416 | let d̂ = camDirection cam -- forward |
@@ -425,7 +434,7 @@ rotate cosθ u = (3><3) | |||
425 | where | 434 | where |
426 | sinθ = sqrt (1 - cosθ * cosθ) | 435 | sinθ = sqrt (1 - cosθ * cosθ) |
427 | mcosθ = 1 - cosθ | 436 | mcosθ = 1 - cosθ |
428 | û = scale (1/realToFrac (norm_2 u)) u | 437 | û = unit u |
429 | ux a = (û!0) * a | 438 | ux a = (û!0) * a |
430 | uy a = (û!1) * a | 439 | uy a = (û!1) * a |
431 | uz a = (û!2) * a | 440 | uz a = (û!2) * a |
@@ -447,7 +456,7 @@ rotate4 cosθ u = (4><4) | |||
447 | where | 456 | where |
448 | sinθ = sqrt (1 - cosθ * cosθ) | 457 | sinθ = sqrt (1 - cosθ * cosθ) |
449 | mcosθ = 1 - cosθ | 458 | mcosθ = 1 - cosθ |
450 | û = scale (1/realToFrac (norm_2 u)) u | 459 | û = unit u |
451 | ux a = (û!0) * a | 460 | ux a = (û!0) * a |
452 | uy a = (û!1) * a | 461 | uy a = (û!1) * a |
453 | uz a = (û!2) * a | 462 | uz a = (û!2) * a |
@@ -507,16 +516,12 @@ sanitizeCamera st = do | |||
507 | modifyIORef (stCamera st) $ \cam -> | 516 | modifyIORef (stCamera st) $ \cam -> |
508 | let d = camDirection cam | 517 | let d = camDirection cam |
509 | u = camUp cam | 518 | u = camUp cam |
510 | dd = norm_2 d | 519 | d̂ = case unit d of |
511 | uu = norm_2 u | 520 | dd | any isNaN (toList dd) -> fromList [0,0,-1] |
512 | e = scale (realToFrac $ 1/dd) d | 521 | | otherwise -> dd |
513 | d̂ = if any isNaN (toList e) | 522 | û = case unit u of |
514 | then fromList [0,0,-1] | 523 | uu | any isNaN (toList uu) -> fromList [0,1,0] |
515 | else e | 524 | | otherwise -> uu |
516 | f = scale (realToFrac $ 1/uu) u | ||
517 | û = if any isNaN (toList f) | ||
518 | then fromList [0,1,0] | ||
519 | else f | ||
520 | in cam | 525 | in cam |
521 | { camDirection = d̂ | 526 | { camDirection = d̂ |
522 | , camUp = û | 527 | , camUp = û |
@@ -538,7 +543,7 @@ worldCoordinates st h k mplane = do | |||
538 | q2 = scale (1 /(q1!3)) $ G.init q1 | 543 | q2 = scale (1 /(q1!3)) $ G.init q1 |
539 | p = camPos cam | 544 | p = camPos cam |
540 | d = q2 - p | 545 | d = q2 - p |
541 | d̂ = scale (1/realToFrac (norm_2 d)) d | 546 | d̂ = unit d |
542 | return $ case mplane of | 547 | return $ case mplane of |
543 | -- Write on the plane. | 548 | -- Write on the plane. |
544 | Just plane -> let n̂ = G.init plane | 549 | Just plane -> let n̂ = G.init plane |
@@ -575,7 +580,9 @@ onEvent w realized ev = do | |||
575 | mev <- get ev #motion | 580 | mev <- get ev #motion |
576 | h <- get mev #x | 581 | h <- get mev #x |
577 | k <- get mev #y | 582 | k <- get mev #y |
578 | case inputSource of | 583 | pd <- readIORef (stDragPlane st) |
584 | case pd of | ||
585 | Nothing -> case inputSource of | ||
579 | Just InputSourcePen -> do | 586 | Just InputSourcePen -> do |
580 | isDown <- readIORef (stPenDown st) | 587 | isDown <- readIORef (stPenDown st) |
581 | when isDown $ do | 588 | when isDown $ do |
@@ -585,12 +592,26 @@ onEvent w realized ev = do | |||
585 | put (h,k) | 592 | put (h,k) |
586 | updateCameraRotation w st h k | 593 | updateCameraRotation w st h k |
587 | return () | 594 | return () |
595 | Just (from,plane) -> do | ||
596 | -- doDragPlane | ||
597 | pos <- camPos <$> readIORef (stCamera st) | ||
598 | n <- subtract pos <$> worldCoordinates st h k Nothing | ||
599 | let n̂ = unit n | ||
600 | p <- worldCoordinates st h k (Just $ n̂ `G.snoc` (from `dot` n̂)) | ||
601 | let δ = dot (p - from) (G.init plane) | ||
602 | writeIORef (stPlane st) $ Just $ plane G.// [(3,δ + plane!3)] | ||
603 | mwin <- widgetGetWindow w | ||
604 | forM_ mwin $ \win -> windowInvalidateRect win Nothing False | ||
605 | putStrLn ("drag-plane " ++ show (δ,p)) | ||
606 | -- end doDragPlane | ||
588 | 607 | ||
589 | EventTypeButtonPress -> do | 608 | EventTypeButtonPress -> do |
590 | bev <- get ev #button | 609 | bev <- get ev #button |
591 | h <- get bev #x | 610 | h <- get bev #x |
592 | k <- get bev #y | 611 | k <- get bev #y |
593 | case inputSource of | 612 | cam <- readIORef (stCamera st) |
613 | if h < realToFrac (camWidth cam) * 0.9 then | ||
614 | case inputSource of | ||
594 | Just InputSourcePen -> do | 615 | Just InputSourcePen -> do |
595 | writeIORef (stPenDown st) True | 616 | writeIORef (stPenDown st) True |
596 | d <- pushRing w st h k | 617 | d <- pushRing w st h k |
@@ -604,12 +625,20 @@ onEvent w realized ev = do | |||
604 | writeIORef (stDragFrom st) $ Just (d,cam) | 625 | writeIORef (stDragFrom st) $ Just (d,cam) |
605 | put (etype,(h,k),d) | 626 | put (etype,(h,k),d) |
606 | return () | 627 | return () |
628 | else do | ||
629 | mplane <- readIORef (stPlane st) | ||
630 | forM_ mplane $ \plane -> do | ||
631 | p <- worldCoordinates st h k mplane | ||
632 | writeIORef (stDragPlane st) $ Just (p,plane) | ||
633 | putStrLn $ "Start plane drag: " ++ show p | ||
607 | 634 | ||
608 | EventTypeButtonRelease -> do | 635 | EventTypeButtonRelease -> do |
609 | bev <- get ev #button | 636 | bev <- get ev #button |
610 | h <- get bev #x | 637 | h <- get bev #x |
611 | k <- get bev #y | 638 | k <- get bev #y |
612 | case inputSource of | 639 | pd <- readIORef (stDragPlane st) |
640 | case pd of | ||
641 | Nothing -> case inputSource of | ||
613 | Just InputSourcePen -> do | 642 | Just InputSourcePen -> do |
614 | writeIORef (stPenDown st) False | 643 | writeIORef (stPenDown st) False |
615 | d <- pushRing w st h k | 644 | d <- pushRing w st h k |
@@ -619,6 +648,20 @@ onEvent w realized ev = do | |||
619 | updateCameraRotation w st h k | 648 | updateCameraRotation w st h k |
620 | sanitizeCamera st | 649 | sanitizeCamera st |
621 | writeIORef (stDragFrom st) Nothing | 650 | writeIORef (stDragFrom st) Nothing |
651 | Just (from,plane) -> do | ||
652 | writeIORef (stDragPlane st) Nothing | ||
653 | -- doDragPlane | ||
654 | pos <- camPos <$> readIORef (stCamera st) | ||
655 | n <- subtract pos <$> worldCoordinates st h k Nothing | ||
656 | let n̂ = unit n | ||
657 | p <- worldCoordinates st h k (Just $ n̂ `G.snoc` (from `dot` n̂)) | ||
658 | let δ = dot (p - from) (G.init plane) | ||
659 | writeIORef (stPlane st) $ Just $ plane G.// [(3,δ + plane!3)] | ||
660 | mwin <- widgetGetWindow w | ||
661 | forM_ mwin $ \win -> windowInvalidateRect win Nothing False | ||
662 | putStrLn ("drag-plane " ++ show (δ,p)) | ||
663 | -- end doDragPlane | ||
664 | |||
622 | 665 | ||
623 | EventTypeScroll -> do | 666 | EventTypeScroll -> do |
624 | sev <- get ev #scroll | 667 | sev <- get ev #scroll |