SVGFonts-0.2: src/Test/PointOfView.hs
module Test.PointOfView where
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT
import Data.IORef
import System(ExitCode(..), exitWith)
import Data.List (nub)
-- import Graphics.UI.GLUT ( Key(SpecialKey, Char) )
setPointOfView :: IORef [Key] -> IORef (GLdouble,GLdouble,GLdouble, GLdouble,GLdouble,GLdouble, GLdouble,GLdouble,GLdouble) -> IO ()
setPointOfView ks pPos = do
keystate <- get ks
if Char 'w' `elem` keystate then do move_vw pPos 0.01 -- vorward
postRedisplay Nothing
else return()
if Char 's' `elem` keystate then do move_vw pPos (negate 0.01) -- backward
postRedisplay Nothing
else return()
if Char 'a' `elem` keystate then do strafe pPos (0.01) -- left
postRedisplay Nothing
else return()
if Char 'd' `elem` keystate then do strafe pPos (negate 0.01)
postRedisplay Nothing -- right
else return()
if (SpecialKey KeyLeft) `elem` keystate then do rot pPos (0,negate 0.002)
postRedisplay Nothing
else return()
if (SpecialKey KeyRight) `elem` keystate then do rot pPos (0, 0.002)
postRedisplay Nothing
else return()
if (SpecialKey KeyUp) `elem` keystate then do rot pPos (0.002, 0)
postRedisplay Nothing
else return()
if (SpecialKey KeyDown) `elem` keystate then do rot pPos (negate 0.002,0)
postRedisplay Nothing
else return()
(x,y,z,lx,ly,lz,ux,uy,uz) <- get pPos
lookAt (Vertex3 x y z) (Vertex3 lx ly lz) (Vector3 ux uy uz) -- x y z: the point where the viewer is situated
-- lx ly lz: the point at which the viewer is looking
-- ux uy uz: a vector, which is up for the viewer
keyboard :: IORef [Key] -> Key -> KeyState -> t -> t1 -> IO ()
keyboard keystate key ks _ _ = do
case (key,ks) of
(Char '\27',_) -> do exitWith ExitSuccess
(Char 'q',_) -> do exitWith ExitSuccess
(_,Down) -> modifyIORef keystate $ nub . (++[key])
(_,Up) -> modifyIORef keystate $ filter (/=key)
--move_vw :: IORef (GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble) -> GLdouble -> IO ()
move_vw pPos delta = do
(x,y,z,lx,ly,lz,ux,uy,uz) <- get pPos
let dx = (lx-x)*delta
dy = (ly-y)*delta
dz = (lz-z)*delta
pPos $= (x+dx, y+dy, z+dz, lx+dx, ly+dy, lz+dz, ux,uy,uz)
kreuz (v0,v1,v2) (w0,w1,w2) = (v1*w2-v2*w1, v2*w0-v0*w2, v0*w1-v1*w0)
kreuz2 (v0,v1,v2,pr) (w0,w1,w2,_) = (v1*w2-v2*w1, v2*w0-v0*w2, v0*w1-v1*w0, pr)
set_len (x,y,z) l = (x*c*l, y*c*l, z*c*l) where c = 1 / v_len (x,y,z)
v_len (x,y,z) = sqrt (x*x+y*y+z*z)
strafe pPos delta = do
(x,y,z,lx,ly,lz,ux,uy,uz) <- get pPos
let (dx, dy, dz) = set_len (kreuz (x-lx,y-ly,z-lz) (ux,uy,uz)) delta
pPos $= (x+dx, y+dy, z+dz, lx+dx, ly+dy, lz+dz, ux,uy,uz)
divide (x,y,z) c = (x/c, y/c, z/c)
mul (x,y,z) c = (x*c, y*c, z*c)
rot pPos (alpha, beta) = do
(px,py,pz,lx,ly,lz,ux,uy,uz) <- get pPos
return (set_len (ux,uy,uz) (v_len (lx-px,ly-py,lz-pz)))
let lx_alpha = px + (lx-px)*(cos alpha) + ux*(sin alpha)
ly_alpha = py + (ly-py)*(cos alpha) + uy*(sin alpha)
lz_alpha = pz + (lz-pz)*(cos alpha) + uz*(sin alpha)
ux_alpha = - (lx-px)*(sin alpha) + ux*(cos alpha)
uy_alpha = - (ly-py)*(sin alpha) + uy*(cos alpha)
uz_alpha = - (lz-pz)*(sin alpha) + uz*(cos alpha)
k = (kreuz (lx_alpha-px, ly_alpha-py, lz_alpha-pz) (ux_alpha, uy_alpha, uz_alpha))
(kx,ky,kz) = (k `divide` (v_len k)) `mul` (v_len (ux, uy, uz))
pPos $= (px, py, pz,
px + (lx_alpha-px)*(cos beta) + kx*(sin beta),
py + (ly_alpha-py)*(cos beta) + ky*(sin beta),
pz + (lz_alpha-pz)*(cos beta) + kz*(sin beta),
ux_alpha, uy_alpha, uz_alpha)
idle pPos = do
postRedisplay Nothing
reshape screenSize@(Size w h) = do
viewport $= ((Position 0 0), screenSize)
matrixMode $= Projection
loadIdentity
let near = 0.001
far = 40
fov = 90
ang = (fov*pi)/(360) -- equals 45 degree
top = near / ( cos(ang) / sin(ang) ) -- top/near has the same value as 1/(x/y)
aspect = fromIntegral(w)/fromIntegral(h)
right = top*aspect
frustum (-right) right (-top) top near far
matrixMode $= Modelview 0