module Vis.Camera ( Camera0(..)
, Camera(..)
, makeCamera
, setCamera
, cameraMotion
, cameraKeyboardMouse
) where
import Graphics.UI.GLUT ( GLdouble, GLint
, Vector3(..), Vertex3(..)
, Position(..), MouseButton(..), Key(..), KeyState(..)
)
import qualified Graphics.UI.GLUT as GLUT
import SpatialMath ( V3(..) )
data Camera0 = Camera0 { phi0 :: GLdouble
, theta0 :: GLdouble
, rho0 :: GLdouble
} deriving Show
data Camera = Camera { phi :: GLdouble
, theta :: GLdouble
, rho :: GLdouble
, pos :: V3 GLdouble
, ballX :: GLint
, ballY :: GLint
, leftButton :: GLint
, rightButton :: GLint
, middleButton :: GLint
}
makeCamera :: Camera0 -> Camera
makeCamera camera0 = Camera { phi = phi0 camera0
, theta = theta0 camera0
, rho = rho0 camera0
, pos = V3 0 0 0
, ballX = (1)
, ballY = (1)
, leftButton = 0
, rightButton = 0
, middleButton = 0
}
setCamera :: Camera -> IO ()
setCamera camera = GLUT.lookAt (Vertex3 xc yc zc) (Vertex3 x0 y0 z0) (Vector3 0 0 (1))
where
V3 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' (V3 x0 y0 z0) bx by lb rb mb) (Position x y) =
Camera nextPhi nextTheta rho0' nextPos nextBallX nextBallY lb rb mb
where
deltaX
| bx == 1 = 0
| otherwise = fromIntegral (x bx)
deltaY
| by == 1 = 0
| otherwise = fromIntegral (y by)
deltaZ
| 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)
nextZ = z0 0.001*rho0'*deltaZ
(nextPhi, nextTheta) = if lb == 1
then (phi0' + deltaX, nextTheta')
else (phi0', theta0')
nextPos
| rb == 1 = V3 nextX nextY z0
| mb == 1 = V3 x0 y0 nextZ
| otherwise = V3 x0 y0 z0
nextBallX = x
nextBallY = y
cameraKeyboardMouse :: Camera -> Key -> KeyState -> Camera
cameraKeyboardMouse camera key keyState =
camera {rho = newRho, leftButton = lb, rightButton = rb, middleButton = mb, 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)
(mb, reset2) = case (key, keyState) of (MouseButton MiddleButton, Down) -> (1, True)
(MouseButton MiddleButton, Up) -> (0, False)
_ -> (middleButton camera, False)
(bx,by) = if reset0 || reset1 || reset2 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)
(Char 'e', Down) -> 0.9 * (rho camera)
(Char 'q', Down) -> 1.1 * (rho camera)
_ -> rho camera