{-# OPTIONS_GHC -Wall #-} module Vis.Camera ( Camera0(..) , Camera(..) , makeCamera , setCamera , cameraMotion , cameraKeyboardMouse ) where import Xyz import Graphics.UI.GLUT data Camera0 = Camera0 { phi0 :: GLdouble , theta0 :: GLdouble , rho0 :: GLdouble } data Camera = Camera { phi :: GLdouble , theta :: GLdouble , rho :: GLdouble , pos :: Xyz GLdouble , ballX :: GLint , ballY :: GLint , leftButton :: GLint , rightButton :: GLint } makeCamera :: Camera0 -> Camera makeCamera camera0 = Camera { phi = phi0 camera0 , theta = theta0 camera0 , rho = rho0 camera0 , pos = Xyz 0 0 0 , ballX = (-1) , ballY = (-1) , leftButton = 0 , rightButton = 0 } setCamera :: Camera -> IO () setCamera camera = lookAt (Vertex3 xc yc zc) (Vertex3 x0 y0 z0) (Vector3 0 0 (-1)) where Xyz x0 y0 z0 = pos camera phi' = phi camera theta' = theta camera rho' = rho camera xc = x0 + rho'*cos(phi'*pi/180)*cos(theta'*pi/180) yc = y0 + rho'*sin(phi'*pi/180)*cos(theta'*pi/180) zc = z0 - rho'*sin(theta'*pi/180) cameraMotion :: Camera -> Position -> Camera cameraMotion (Camera phi0' theta0' rho0' (Xyz x0 y0 z0) bx by lb rb) (Position x y) = Camera nextPhi nextTheta rho0' nextPos nextBallX nextBallY lb rb where deltaX | bx == -1 = 0 | otherwise = fromIntegral (x - bx) deltaY | by == -1 = 0 | otherwise = fromIntegral (y - by) nextTheta' | deltaY + theta0' > 80 = 80 | deltaY + theta0' < -80 = -80 | otherwise = deltaY + theta0' nextX = x0 + 0.003*rho0'*( -sin(phi0'*pi/180)*deltaX - cos(phi0'*pi/180)*deltaY) nextY = y0 + 0.003*rho0'*( cos(phi0'*pi/180)*deltaX - sin(phi0'*pi/180)*deltaY) (nextPhi, nextTheta) = if lb == 1 then (phi0' + deltaX, nextTheta') else (phi0', theta0') nextPos = if rb == 1 then Xyz nextX nextY z0 else Xyz x0 y0 z0 nextBallX = x nextBallY = y cameraKeyboardMouse :: Camera -> Key -> KeyState -> Camera cameraKeyboardMouse camera key keyState = camera {rho = newRho, leftButton = lb, rightButton = rb, ballX = bx, ballY = by} where (lb, reset0) = case (key, keyState) of (MouseButton LeftButton, Down) -> (1, True) (MouseButton LeftButton, Up) -> (0, False) _ -> (leftButton camera, False) (rb, reset1) = case (key, keyState) of (MouseButton RightButton, Down) -> (1, True) (MouseButton RightButton, Up) -> (0, False) _ -> (rightButton camera, False) (bx,by) = if reset0 || reset1 then (-1,-1) else (ballX camera, ballY camera) newRho = case (key, keyState) of (MouseButton WheelUp, Down) -> 0.9 * (rho camera) (MouseButton WheelDown, Down) -> 1.1 * (rho camera) _ -> rho camera