aboutsummaryrefslogtreecommitdiff
path: root/Spear/Math/Spatial3.hs
blob: 9f9812f76fb30c6d07984e6c16497a07eab544d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
module Spear.Math.Spatial3
where


import Spear.Math.Vector3
import Spear.Math.Matrix4 as M


class Spatial3 s where
    -- | Move the 'Spatial'.
    move :: Vector3 -> s -> s
    
    -- | Move the 'Spatial' forwards.
    moveFwd :: Float -> s -> s
    
    -- | Move the 'Spatial' backwards.
    moveBack :: Float -> s -> s
    
    -- | Make the 'Spatial' strafe left.
    strafeLeft :: Float -> s -> s
    
    -- | Make the 'Spatial' Strafe right.
    strafeRight :: Float -> s -> s
    
    -- | Rotate the 'Spatial' about its local X axis.
    pitch :: Float -> s -> s
    
    -- | Rotate the 'Spatial' about its local Y axis.
    yaw :: Float -> s -> s
    
    -- | Rotate the 'Spatial' about its local Z axis.
    roll :: Float -> s -> s
    
    -- | Get the 'Spatial''s position.
    pos :: s -> Vector3
    
    -- | Get the 'Spatial''s forward vector.
    fwd :: s -> Vector3
    
    -- | Get the 'Spatial''s up vector.
    up :: s -> Vector3
    
    -- | Get the 'Spatial''s right vector.
    right :: s -> Vector3
    
    -- | Get the 'Spatial''s transform.
    transform :: s -> Matrix4
    
    -- | Set the 'Spatial''s transform.
    setTransform :: Matrix4 -> s -> s
    
    -- | Set the 'Spatial''s position.
    setPos :: Vector3 -> s -> s
    
    -- | Make the 'Spatial' look at the given point.
    lookAt :: Vector3 -> s -> s
    lookAt pt s =
        let position = pos s
            fwd      = normalise $ pt - position
            r        = fwd `cross` unitY
            u        = r `cross` fwd
        in
            setTransform (M.transform r u (-fwd) position) s
    
    -- | Make the 'Spatial' orbit around the given point
    orbit :: Vector3 -- ^ Target point
          -> Float   -- ^ Horizontal angle
          -> Float   -- ^ Vertical angle
          -> Float   -- ^ Orbit radius.
          -> s
          -> s
    
    orbit pt anglex angley radius s =
        let ax = anglex * pi / 180
            ay = angley * pi / 180
            sx = sin ax
            sy = sin ay
            cx = cos ax
            cy = cos ay
            px = (x pt) + radius*cy*sx
            py = (y pt) + radius*sy
            pz = (z pt) + radius*cx*cy
        in
            setPos (vec3 px py pz) s