diff options
author | Joe Crayne <joe@jerkface.net> | 2019-04-29 21:31:50 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-04-29 21:31:50 -0400 |
commit | 051f60000748548b04084aca77bc30b11d7bf2db (patch) | |
tree | da1f75558526ed60a17d4d537b024f97e95a6528 | |
parent | 4c98ccde118f4dd0503226154876001bfc2770f7 (diff) |
Camera object.
-rw-r--r-- | MeshSketch.hs | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs index 9c6c457..675c388 100644 --- a/MeshSketch.hs +++ b/MeshSketch.hs | |||
@@ -43,8 +43,46 @@ import Matrix | |||
43 | data State = State | 43 | data State = State |
44 | { stTimeKeeper :: TimeKeeper | 44 | { stTimeKeeper :: TimeKeeper |
45 | , stTickCallback :: TickCallbackHandle | 45 | , stTickCallback :: TickCallbackHandle |
46 | , stCamera :: IORef Camera | ||
46 | } | 47 | } |
47 | 48 | ||
49 | data Camera = Camera | ||
50 | { camHeightAngle :: Float | ||
51 | , camTarget :: Vector Float | ||
52 | , camDirection :: Vector Float | ||
53 | , camDistance :: Float | ||
54 | , camWidth :: Float | ||
55 | , camHeight :: Float | ||
56 | , camUp :: Vector Float | ||
57 | , camWorldToScreen :: Maybe (Matrix Float) | ||
58 | , camScreenToWorld :: Maybe (Matrix Float) | ||
59 | } | ||
60 | |||
61 | initCamera :: Camera | ||
62 | initCamera = Camera | ||
63 | { camHeightAngle = pi/6 | ||
64 | , camTarget = fromList [0,0,0] | ||
65 | , camDirection = scale (1/d) $ fromList [-2,-2,-10] | ||
66 | , camDistance = d | ||
67 | , camWidth = 700 | ||
68 | , camHeight = 700 | ||
69 | , camUp = fromList [0,1,0] | ||
70 | , camWorldToScreen = Nothing | ||
71 | , camScreenToWorld = Nothing | ||
72 | } | ||
73 | where d = realToFrac $ norm_2 $ fromList [2::Float,2,10] | ||
74 | |||
75 | viewProjection :: Camera -> (Camera,(Matrix Float,Vector Float)) | ||
76 | viewProjection c | ||
77 | | Just m <- camWorldToScreen c = (c,(m,pos)) | ||
78 | | otherwise = (c { camWorldToScreen = Just m' }, (m',pos)) | ||
79 | where | ||
80 | m' = proj <> cam | ||
81 | cam = lookat pos (camTarget c) (camUp c) | ||
82 | pos = camTarget c - scale (camDistance c) (camDirection c) | ||
83 | proj = perspective 0.1 100 (camHeightAngle c) (camWidth c / camHeight c) | ||
84 | |||
85 | |||
48 | addOBJToObjectArray :: GLStorage -> String -> [(GPUMesh, Maybe Text)] -> Map Text (ObjMaterial,TextureData) -> IO [LC.Object] | 86 | addOBJToObjectArray :: GLStorage -> String -> [(GPUMesh, Maybe Text)] -> Map Text (ObjMaterial,TextureData) -> IO [LC.Object] |
49 | addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat) -> do | 87 | addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat) -> do |
50 | obj <- LC.addMeshToObjectArray storage slotName ["diffuseTexture","diffuseColor"] mesh | 88 | obj <- LC.addMeshToObjectArray storage slotName ["diffuseTexture","diffuseColor"] mesh |
@@ -70,11 +108,13 @@ uploadState obj glarea storage = do | |||
70 | 108 | ||
71 | -- setup FrameClock | 109 | -- setup FrameClock |
72 | tm <- newTimeKeeper | 110 | tm <- newTimeKeeper |
111 | cam <- newIORef initCamera | ||
73 | tickcb <- widgetAddTickCallback glarea (tick tm) | 112 | tickcb <- widgetAddTickCallback glarea (tick tm) |
74 | 113 | ||
75 | return State | 114 | return State |
76 | { stTimeKeeper = tm | 115 | { stTimeKeeper = tm |
77 | , stTickCallback = tickcb | 116 | , stTickCallback = tickcb |
117 | , stCamera = cam | ||
78 | } | 118 | } |
79 | 119 | ||
80 | destroyState :: GLArea -> State -> IO () | 120 | destroyState :: GLArea -> State -> IO () |
@@ -89,12 +129,23 @@ setUniforms gl storage st = do | |||
89 | t <- (/ 10.0) <$> getSeconds (stTimeKeeper st) | 129 | t <- (/ 10.0) <$> getSeconds (stTimeKeeper st) |
90 | let tf = realToFrac t :: Float | 130 | let tf = realToFrac t :: Float |
91 | rot = rotMatrixZ (-tf) <> rotMatrixX (-tf) | 131 | rot = rotMatrixZ (-tf) <> rotMatrixX (-tf) |
92 | pos = rot #> fromList [2,2,10] | 132 | modifyIORef (stCamera st) $ \cam -> cam |
133 | { camUp = rot #> fromList [0,1,0] | ||
134 | , camDirection = (scale (1/camDistance cam) $ fromList [-2,-2,-10]) <# rot | ||
135 | , camWorldToScreen = Nothing | ||
136 | , camScreenToWorld = Nothing | ||
137 | } | ||
138 | |||
139 | (mvp,pos) <- atomicModifyIORef' (stCamera st) viewProjection | ||
140 | |||
141 | {- | ||
142 | let pos = rot #> fromList [2,2,10] | ||
93 | up = rot #> fromList [0,1,0] | 143 | up = rot #> fromList [0,1,0] |
94 | cam = lookat pos 0 up | 144 | view = lookat pos 0 up |
95 | aspect = 1 | 145 | aspect = 1 |
96 | proj = perspective 0.1 100 deg30 aspect | 146 | proj = perspective 0.1 100 deg30 aspect |
97 | mvp = proj <> cam | 147 | mvp = proj <> view |
148 | -} | ||
98 | 149 | ||
99 | LC.updateUniforms storage $ do | 150 | LC.updateUniforms storage $ do |
100 | "CameraPosition" @= return (pos :: Vector Float) | 151 | "CameraPosition" @= return (pos :: Vector Float) |
@@ -187,4 +238,8 @@ onResize glarea realized w h = do | |||
187 | (wd,ht) <- do wd <- windowGetWidth win | 238 | (wd,ht) <- do wd <- windowGetWidth win |
188 | ht <- windowGetHeight win | 239 | ht <- windowGetHeight win |
189 | return (fromIntegral wd,fromIntegral ht) | 240 | return (fromIntegral wd,fromIntegral ht) |
241 | modifyIORef' (stCamera $ stState realized) | ||
242 | $ \c -> c { camWidth = fromIntegral wd | ||
243 | , camHeight = fromIntegral ht | ||
244 | } | ||
190 | LC.setScreenSize (stStorage realized) wd ht) | 245 | LC.setScreenSize (stStorage realized) wd ht) |