aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Spear/App/Input.hs40
-rw-r--r--Spear/GL.hs3
-rw-r--r--Spear/Math/Camera.hs100
-rw-r--r--Spear/Math/MatrixUtils.hs9
-rw-r--r--Spear/Math/Spatial3.hs134
-rw-r--r--Spear/Scene/GameObject.hs3
6 files changed, 176 insertions, 113 deletions
diff --git a/Spear/App/Input.hs b/Spear/App/Input.hs
index 0207147..9fa140a 100644
--- a/Spear/App/Input.hs
+++ b/Spear/App/Input.hs
@@ -27,14 +27,12 @@ module Spear.App.Input
27) 27)
28where 28where
29 29
30
31import Data.Char (ord) 30import Data.Char (ord)
32import qualified Data.Vector.Unboxed as V 31import qualified Data.Vector.Unboxed as V
33import qualified Graphics.UI.GLFW as GLFW 32import qualified Graphics.UI.GLFW as GLFW
34import Graphics.Rendering.OpenGL.GL.CoordTrans 33import Graphics.Rendering.OpenGL.GL.CoordTrans
35import Data.StateVar 34import Data.StateVar
36 35
37
38data Key 36data Key
39 = KEY_A | KEY_B | KEY_C | KEY_D | KEY_E | KEY_F | KEY_G | KEY_H 37 = KEY_A | KEY_B | KEY_C | KEY_D | KEY_E | KEY_F | KEY_G | KEY_H
40 | KEY_I | KEY_J | KEY_K | KEY_L | KEY_M | KEY_N | KEY_O | KEY_P 38 | KEY_I | KEY_J | KEY_K | KEY_L | KEY_M | KEY_N | KEY_O | KEY_P
@@ -42,33 +40,28 @@ data Key
42 | KEY_Y | KEY_Z | KEY_0 | KEY_1 | KEY_2 | KEY_3 | KEY_4 | KEY_5 40 | KEY_Y | KEY_Z | KEY_0 | KEY_1 | KEY_2 | KEY_3 | KEY_4 | KEY_5
43 | KEY_6 | KEY_7 | KEY_8 | KEY_9 | KEY_F1 | KEY_F2 | KEY_F3 41 | KEY_6 | KEY_7 | KEY_8 | KEY_9 | KEY_F1 | KEY_F2 | KEY_F3
44 | KEY_F4 | KEY_F5 | KEY_F6 | KEY_F7 | KEY_F8 | KEY_F9 | KEY_F10 42 | KEY_F4 | KEY_F5 | KEY_F6 | KEY_F7 | KEY_F8 | KEY_F9 | KEY_F10
45 | KEY_F11 | KEY_F12 | KEY_ESC | KEY_SPACE 43 | KEY_F11 | KEY_F12 | KEY_ESC | KEY_SPACE | KEY_UP | KEY_DOWN
44 | KEY_LEFT | KEY_RIGHT
46 deriving (Enum, Bounded) 45 deriving (Enum, Bounded)
47 46
48
49type Keyboard = Key -> Bool 47type Keyboard = Key -> Bool
50 48
51
52data MouseButton = LMB | RMB | MMB 49data MouseButton = LMB | RMB | MMB
53 deriving (Enum, Bounded) 50 deriving (Enum, Bounded)
54 51
55
56data MouseProp = MouseX | MouseY | MouseDX | MouseDY 52data MouseProp = MouseX | MouseY | MouseDX | MouseDY
57 deriving Enum 53 deriving Enum
58 54
59
60data Mouse = Mouse 55data Mouse = Mouse
61 { button :: MouseButton -> Bool 56 { button :: MouseButton -> Bool
62 , property :: MouseProp -> Float 57 , property :: MouseProp -> Float
63 } 58 }
64 59
65
66data Input = Input 60data Input = Input
67 { keyboard :: Keyboard 61 { keyboard :: Keyboard
68 , mouse :: Mouse 62 , mouse :: Mouse
69 } 63 }
70 64
71
72-- | Return a new dummy keyboard. 65-- | Return a new dummy keyboard.
73-- 66--
74-- This function should be called to get an initial keyboard. 67-- This function should be called to get an initial keyboard.
@@ -79,7 +72,6 @@ data Input = Input
79newKeyboard :: Keyboard 72newKeyboard :: Keyboard
80newKeyboard = const False 73newKeyboard = const False
81 74
82
83-- | Get the keyboard. 75-- | Get the keyboard.
84getKeyboard :: IO Keyboard 76getKeyboard :: IO Keyboard
85getKeyboard = 77getKeyboard =
@@ -90,7 +82,6 @@ getKeyboard =
90 (fmap (V.fromList . fmap ((==) GLFW.Press)) . mapM GLFW.getKey . fmap toGLFWkey $ keys) 82 (fmap (V.fromList . fmap ((==) GLFW.Press)) . mapM GLFW.getKey . fmap toGLFWkey $ keys)
91 >>= return . keyboard' 83 >>= return . keyboard'
92 84
93
94-- | Return a new dummy mouse. 85-- | Return a new dummy mouse.
95-- 86--
96-- This function should be called to get an initial mouse. 87-- This function should be called to get an initial mouse.
@@ -101,7 +92,6 @@ getKeyboard =
101newMouse :: Mouse 92newMouse :: Mouse
102newMouse = Mouse (const False) (const 0) 93newMouse = Mouse (const False) (const 0)
103 94
104
105-- | Get the mouse. 95-- | Get the mouse.
106-- 96--
107-- The previous mouse state is required to compute position deltas. 97-- The previous mouse state is required to compute position deltas.
@@ -109,21 +99,21 @@ getMouse :: Mouse -> IO Mouse
109getMouse oldMouse = 99getMouse oldMouse =
110 let getButton :: V.Vector Bool -> MouseButton -> Bool 100 let getButton :: V.Vector Bool -> MouseButton -> Bool
111 getButton mousestate button = mousestate V.! fromEnum button 101 getButton mousestate button = mousestate V.! fromEnum button
112 102
113 getProp :: V.Vector Float -> MouseProp -> Float 103 getProp :: V.Vector Float -> MouseProp -> Float
114 getProp props prop = props V.! fromEnum prop 104 getProp props prop = props V.! fromEnum prop
115 105
116 props xpos ypos = V.fromList 106 props xpos ypos = V.fromList
117 [ xpos, ypos 107 [ xpos, ypos
118 , xpos - property oldMouse MouseX 108 , xpos - property oldMouse MouseX
119 , ypos - property oldMouse MouseY 109 , ypos - property oldMouse MouseY
120 ] 110 ]
121 111
122 getButtonState = 112 getButtonState =
123 fmap (V.fromList . fmap ((==) GLFW.Press)) . 113 fmap (V.fromList . fmap ((==) GLFW.Press)) .
124 mapM GLFW.getMouseButton . 114 mapM GLFW.getMouseButton .
125 fmap toGLFWbutton $ buttons 115 fmap toGLFWbutton $ buttons
126 116
127 buttons = fmap toEnum [0..fromEnum (maxBound :: MouseButton)] 117 buttons = fmap toEnum [0..fromEnum (maxBound :: MouseButton)]
128 in do 118 in do
129 Position xpos ypos <- get GLFW.mousePos 119 Position xpos ypos <- get GLFW.mousePos
@@ -133,12 +123,10 @@ getMouse oldMouse =
133 , property = getProp $ props (fromIntegral xpos) (fromIntegral ypos) 123 , property = getProp $ props (fromIntegral xpos) (fromIntegral ypos)
134 } 124 }
135 125
136
137-- | Return a new dummy input. 126-- | Return a new dummy input.
138newInput :: Input 127newInput :: Input
139newInput = Input newKeyboard newMouse 128newInput = Input newKeyboard newMouse
140 129
141
142-- | Get input devices. 130-- | Get input devices.
143getInput :: Input -> IO Input 131getInput :: Input -> IO Input
144getInput (Input _ oldMouse) = do 132getInput (Input _ oldMouse) = do
@@ -146,12 +134,10 @@ getInput (Input _ oldMouse) = do
146 mouse <- getMouse oldMouse 134 mouse <- getMouse oldMouse
147 return $ Input keyboard mouse 135 return $ Input keyboard mouse
148 136
149
150-- | Poll input devices. 137-- | Poll input devices.
151pollInput :: IO () 138pollInput :: IO ()
152pollInput = GLFW.pollEvents 139pollInput = GLFW.pollEvents
153 140
154
155-- | Return a mouse that reacts to button toggles. 141-- | Return a mouse that reacts to button toggles.
156toggledMouse :: Mouse -- ^ Previous mouse state. 142toggledMouse :: Mouse -- ^ Previous mouse state.
157 -> Mouse -- ^ Current mouse state. 143 -> Mouse -- ^ Current mouse state.
@@ -159,7 +145,6 @@ toggledMouse :: Mouse -- ^ Previous mouse state.
159 145
160toggledMouse prev cur = cur { button = \bt -> button cur bt && not (button prev bt) } 146toggledMouse prev cur = cur { button = \bt -> button cur bt && not (button prev bt) }
161 147
162
163-- | Return a keyboard that reacts to key toggles. 148-- | Return a keyboard that reacts to key toggles.
164toggledKeyboard :: Keyboard -- ^ Previous keyboard state. 149toggledKeyboard :: Keyboard -- ^ Previous keyboard state.
165 -> Keyboard -- ^ Current keyboard state. 150 -> Keyboard -- ^ Current keyboard state.
@@ -167,9 +152,6 @@ toggledKeyboard :: Keyboard -- ^ Previous keyboard state.
167 152
168toggledKeyboard prev cur key = cur key && not (prev key) 153toggledKeyboard prev cur key = cur key && not (prev key)
169 154
170
171
172
173-- | Delay configuration for each mouse button. 155-- | Delay configuration for each mouse button.
174type ButtonDelay = MouseButton -> Float 156type ButtonDelay = MouseButton -> Float
175 157
@@ -181,13 +163,11 @@ data DelayedMouse = DelayedMouse
181 , accum :: V.Vector Float 163 , accum :: V.Vector Float
182 } 164 }
183 165
184
185newDM :: ButtonDelay -- ^ Delay configuration for each button. 166newDM :: ButtonDelay -- ^ Delay configuration for each button.
186 -> DelayedMouse 167 -> DelayedMouse
187newDM delay = DelayedMouse newMouse delay $ 168newDM delay = DelayedMouse newMouse delay $
188 V.replicate (fromEnum (maxBound :: MouseButton)) 0 169 V.replicate (fromEnum (maxBound :: MouseButton)) 0
189 170
190
191updateDM :: DelayedMouse -- ^ Current mouse state. 171updateDM :: DelayedMouse -- ^ Current mouse state.
192 -> Float -- ^ Time elapsed since last udpate. 172 -> Float -- ^ Time elapsed since last udpate.
193 -> DelayedMouse 173 -> DelayedMouse
@@ -199,13 +179,11 @@ updateDM (DelayedMouse mouse delay accum) dt =
199 button' b = active b && button mouse b 179 button' b = active b && button mouse b
200 accum' = accum V.// fmap newDelay [0 .. fromEnum (maxBound :: MouseButton)] 180 accum' = accum V.// fmap newDelay [0 .. fromEnum (maxBound :: MouseButton)]
201 newDelay x = let b = toEnum x 181 newDelay x = let b = toEnum x
202 in (x, if button' b then 0 else time b) 182 in (x, if button' b then 0 else time b)
203 in 183 in
204 DelayedMouse mouse { button = button' } delay accum' 184 DelayedMouse mouse { button = button' } delay accum'
205 185
206 186
207
208
209toGLFWkey :: Key -> Int 187toGLFWkey :: Key -> Int
210toGLFWkey KEY_A = ord 'A' 188toGLFWkey KEY_A = ord 'A'
211toGLFWkey KEY_B = ord 'B' 189toGLFWkey KEY_B = ord 'B'
@@ -257,6 +235,10 @@ toGLFWkey KEY_F11 = fromEnum GLFW.F11
257toGLFWkey KEY_F12 = fromEnum GLFW.F12 235toGLFWkey KEY_F12 = fromEnum GLFW.F12
258toGLFWkey KEY_ESC = fromEnum GLFW.ESC 236toGLFWkey KEY_ESC = fromEnum GLFW.ESC
259toGLFWkey KEY_SPACE = ord ' ' 237toGLFWkey KEY_SPACE = ord ' '
238toGLFWkey KEY_UP = fromEnum GLFW.UP
239toGLFWkey KEY_DOWN = fromEnum GLFW.DOWN
240toGLFWkey KEY_LEFT = fromEnum GLFW.LEFT
241toGLFWkey KEY_RIGHT = fromEnum GLFW.RIGHT
260 242
261 243
262toGLFWbutton :: MouseButton -> GLFW.MouseButton 244toGLFWbutton :: MouseButton -> GLFW.MouseButton
diff --git a/Spear/GL.hs b/Spear/GL.hs
index 6792d35..af96da4 100644
--- a/Spear/GL.hs
+++ b/Spear/GL.hs
@@ -452,7 +452,8 @@ attribVAOPointer
452 -> Int -- ^ Offset to the first component in the array. 452 -> Int -- ^ Offset to the first component in the array.
453 -> IO () 453 -> IO ()
454attribVAOPointer idx ncomp dattype normalise stride off = 454attribVAOPointer idx ncomp dattype normalise stride off =
455 glVertexAttribPointer idx ncomp dattype (unsafeCoerce normalise) stride (unsafeCoerce off) 455 glVertexAttribPointer idx ncomp dattype normalise' stride (unsafeCoerce off)
456 where normalise' = if normalise then 1 else 0
456 457
457-- | Draw the bound vao. 458-- | Draw the bound vao.
458drawArrays 459drawArrays
diff --git a/Spear/Math/Camera.hs b/Spear/Math/Camera.hs
index a86d5f5..9484bef 100644
--- a/Spear/Math/Camera.hs
+++ b/Spear/Math/Camera.hs
@@ -1,71 +1,89 @@
1module Spear.Math.Camera 1module Spear.Math.Camera
2(
3 Camera
4, Fovy
5, Aspect
6, Near
7, Far
8, Left
9, Right
10, Bottom
11, Top
12, projection
13)
2where 14where
3 15
4 16
5import qualified Spear.Math.Matrix4 as M 17import qualified Spear.Math.Matrix4 as M
6import qualified Spear.Math.Spatial3 as S 18import Spear.Math.Spatial3
7import Spear.Math.Vector 19import Spear.Math.Vector
8 20
9 21
10data Camera = Camera 22data Camera = Camera
11 { projection :: M.Matrix4 23 { projection :: M.Matrix4 -- ^ Get the camera's projection.
12 , transform :: M.Matrix4 24 , spatial :: Obj3
13 } 25 }
14 26
27type Fovy = Float
28type Aspect = Float
29type Near = Float
30type Far = Float
31type Left = Float
32type Right = Float
33type Bottom = Float
34type Top = Float
15 35
16-- | Build a perspective camera. 36-- | Build a perspective camera.
17perspective :: Float -- ^ Fovy - Vertical field of view angle in degrees. 37perspective :: Fovy -- ^ Fovy - Vertical field of view angle in degrees.
18 -> Float -- ^ Aspect ratio. 38 -> Aspect -- ^ Aspect ratio.
19 -> Float -- ^ Near clip. 39 -> Near -- ^ Near clip.
20 -> Float -- ^ Far clip. 40 -> Far -- ^ Far clip.
21 -> Vector3 -- ^ Right vector. 41 -> Right3 -- ^ Right vector.
22 -> Vector3 -- ^ Up vector. 42 -> Up3 -- ^ Up vector.
23 -> Vector3 -- ^ Forward vector. 43 -> Forward3 -- ^ Forward vector.
24 -> Vector3 -- ^ Position vector. 44 -> Position3 -- ^ Position vector.
25 -> Camera 45 -> Camera
26 46
27perspective fovy r n f right up fwd pos = 47perspective fovy r n f right up fwd pos =
28 Camera 48 Camera
29 { projection = M.perspective fovy r n f 49 { projection = M.perspective fovy r n f
30 , transform = M.transform right up (neg fwd) pos 50 , spatial = fromVectors right up fwd pos
31 } 51 }
32 52
33 53
34-- | Build an orthogonal camera. 54-- | Build an orthogonal camera.
35ortho :: Float -- ^ Left. 55ortho :: Left -- ^ Left.
36 -> Float -- ^ Right. 56 -> Right -- ^ Right.
37 -> Float -- ^ Bottom. 57 -> Bottom -- ^ Bottom.
38 -> Float -- ^ Top. 58 -> Top -- ^ Top.
39 -> Float -- ^ Near clip. 59 -> Near -- ^ Near clip.
40 -> Float -- ^ Far clip. 60 -> Far -- ^ Far clip.
41 -> Vector3 -- ^ Right vector. 61 -> Right3 -- ^ Right vector.
42 -> Vector3 -- ^ Up vector. 62 -> Up3 -- ^ Up vector.
43 -> Vector3 -- ^ Forward vector. 63 -> Forward3 -- ^ Forward vector.
44 -> Vector3 -- ^ Position vector. 64 -> Position3 -- ^ Position vector.
45 -> Camera 65 -> Camera
46 66
47ortho l r b t n f right up fwd pos = 67ortho l r b t n f right up fwd pos =
48 Camera 68 Camera
49 { projection = M.ortho l r b t n f 69 { projection = M.ortho l r b t n f
50 , transform = M.transform right up (neg fwd) pos 70 , spatial = fromVectors right up fwd pos
51 } 71 }
52 72
53 73
54instance S.Spatial3 Camera where 74instance Spatial3 Camera where
55 move v cam = cam { transform = M.translv v * transform cam } 75 move v cam = cam { spatial = move v $ spatial cam }
56 moveFwd f cam = cam { transform = M.translv (scale f $ S.fwd cam) * transform cam } 76 moveFwd s cam = cam { spatial = moveFwd s $ spatial cam }
57 moveBack f cam = cam { transform = M.translv (scale (-f) $ S.fwd cam) * transform cam } 77 moveBack s cam = cam { spatial = moveBack s $ spatial cam }
58 strafeLeft f cam = cam { transform = M.translv (scale (-f) $ S.right cam) * transform cam } 78 strafeLeft s cam = cam { spatial = strafeLeft s $ spatial cam }
59 strafeRight f cam = cam { transform = M.translv (scale f $ S.right cam) * transform cam } 79 strafeRight s cam = cam { spatial = strafeRight s $ spatial cam }
60 pitch a cam = cam { transform = transform cam * M.axisAngle (S.right cam) a } 80 pitch a cam = cam { spatial = pitch a $ spatial cam }
61 yaw a cam = cam { transform = transform cam * M.axisAngle (S.up cam) a } 81 yaw a cam = cam { spatial = yaw a $ spatial cam }
62 roll a cam = cam { transform = transform cam * M.axisAngle (S.fwd cam) a } 82 roll a cam = cam { spatial = roll a $ spatial cam }
63 pos = M.position . transform 83 pos cam = pos $ spatial cam
64 fwd = M.forward . transform 84 fwd cam = fwd $ spatial cam
65 up = M.up . transform 85 up cam = up $ spatial cam
66 right = M.right . transform 86 right cam = right $ spatial cam
67 transform (Camera _ t) = t 87 transform cam = transform $ spatial cam
68 setTransform t (Camera proj _) = Camera proj t 88 setTransform m cam = cam { spatial = setTransform m $ spatial cam }
69 setPos pos (Camera proj t) = Camera proj $ 89 setPos p cam = cam { spatial = setPos p $ spatial cam }
70 M.transform (M.right t) (M.up t) (M.forward t) pos
71
diff --git a/Spear/Math/MatrixUtils.hs b/Spear/Math/MatrixUtils.hs
index 79bd049..e4273a1 100644
--- a/Spear/Math/MatrixUtils.hs
+++ b/Spear/Math/MatrixUtils.hs
@@ -15,6 +15,7 @@ where
15import Spear.Math.Camera as Cam 15import Spear.Math.Camera as Cam
16import Spear.Math.Matrix3 as M3 16import Spear.Math.Matrix3 as M3
17import Spear.Math.Matrix4 as M4 17import Spear.Math.Matrix4 as M4
18import Spear.Math.Spatial3 as S
18import Spear.Math.Vector as V 19import Spear.Math.Vector as V
19 20
20 21
@@ -112,7 +113,7 @@ pltTransform mat =
112 113
113 114
114-- | Map an object's transform in world space to view space. 115-- | Map an object's transform in world space to view space.
115-- 116--
116-- The XY plane in 2D translates to the X(-Z) plane in 3D. 117-- The XY plane in 2D translates to the X(-Z) plane in 3D.
117-- 118--
118-- Use this in games such as RPGs and RTSs. 119-- Use this in games such as RPGs and RTSs.
@@ -130,9 +131,9 @@ rpgInverse h a axis pos viewI =
130-- | Map an object's transform in world space to view space. 131-- | Map an object's transform in world space to view space.
131-- 132--
132-- This function maps an object's transform in 2D to the object's inverse in 3D. 133-- This function maps an object's transform in 2D to the object's inverse in 3D.
133-- 134--
134-- The XY plane in 2D translates to the XY plane in 3D. 135-- The XY plane in 2D translates to the XY plane in 3D.
135-- 136--
136-- Use this in games like platformers and space invaders style games. 137-- Use this in games like platformers and space invaders style games.
137pltInverse :: Matrix3 -> Matrix4 138pltInverse :: Matrix3 -> Matrix4
138pltInverse = M4.inverseTransform . pltTransform 139pltInverse = M4.inverseTransform . pltTransform
@@ -142,7 +143,7 @@ pltInverse = M4.inverseTransform . pltTransform
142objToClip :: Camera -> Matrix4 -> Vector3 -> Vector2 143objToClip :: Camera -> Matrix4 -> Vector3 -> Vector2
143objToClip cam model p = 144objToClip cam model p =
144 let 145 let
145 view = M4.inverseTransform $ Cam.transform cam 146 view = M4.inverseTransform $ S.transform cam
146 proj = Cam.projection cam 147 proj = Cam.projection cam
147 p' = (proj * view * model) `M4.mulp` p 148 p' = (proj * view * model) `M4.mulp` p
148 in 149 in
diff --git a/Spear/Math/Spatial3.hs b/Spear/Math/Spatial3.hs
index 6db3853..2bc772e 100644
--- a/Spear/Math/Spatial3.hs
+++ b/Spear/Math/Spatial3.hs
@@ -1,58 +1,62 @@
1module Spear.Math.Spatial3 1module Spear.Math.Spatial3
2(
3 Spatial3(..)
4, Obj3
5, fromVectors
6, fromTransform
7)
2where 8where
3 9
4
5import Spear.Math.Vector 10import Spear.Math.Vector
6import Spear.Math.Matrix4 as M 11import Spear.Math.Matrix4 as M hiding (scale)
7
8 12
9class Spatial3 s where 13class Spatial3 s where
10 -- | Move the 'Spatial'. 14 -- | Move the spatial.
11 move :: Vector3 -> s -> s 15 move :: Vector3 -> s -> s
12 16
13 -- | Move the 'Spatial' forwards. 17 -- | Move the spatial forwards.
14 moveFwd :: Float -> s -> s 18 moveFwd :: Float -> s -> s
15 19
16 -- | Move the 'Spatial' backwards. 20 -- | Move the spatial backwards.
17 moveBack :: Float -> s -> s 21 moveBack :: Float -> s -> s
18 22
19 -- | Make the 'Spatial' strafe left. 23 -- | Make the spatial strafe left.
20 strafeLeft :: Float -> s -> s 24 strafeLeft :: Float -> s -> s
21 25
22 -- | Make the 'Spatial' Strafe right. 26 -- | Make the spatial Strafe right.
23 strafeRight :: Float -> s -> s 27 strafeRight :: Float -> s -> s
24 28
25 -- | Rotate the 'Spatial' about its local X axis. 29 -- | Rotate the spatial about its local X axis.
26 pitch :: Float -> s -> s 30 pitch :: Float -> s -> s
27 31
28 -- | Rotate the 'Spatial' about its local Y axis. 32 -- | Rotate the spatial about its local Y axis.
29 yaw :: Float -> s -> s 33 yaw :: Float -> s -> s
30 34
31 -- | Rotate the 'Spatial' about its local Z axis. 35 -- | Rotate the spatial about its local Z axis.
32 roll :: Float -> s -> s 36 roll :: Float -> s -> s
33 37
34 -- | Get the 'Spatial''s position. 38 -- | Get the spatial's position.
35 pos :: s -> Vector3 39 pos :: s -> Vector3
36 40
37 -- | Get the 'Spatial''s forward vector. 41 -- | Get the spatial's forward vector.
38 fwd :: s -> Vector3 42 fwd :: s -> Vector3
39 43
40 -- | Get the 'Spatial''s up vector. 44 -- | Get the spatial's up vector.
41 up :: s -> Vector3 45 up :: s -> Vector3
42 46
43 -- | Get the 'Spatial''s right vector. 47 -- | Get the spatial's right vector.
44 right :: s -> Vector3 48 right :: s -> Vector3
45 49
46 -- | Get the 'Spatial''s transform. 50 -- | Get the spatial's transform.
47 transform :: s -> Matrix4 51 transform :: s -> Matrix4
48 52
49 -- | Set the 'Spatial''s transform. 53 -- | Set the spatial's transform.
50 setTransform :: Matrix4 -> s -> s 54 setTransform :: Matrix4 -> s -> s
51 55
52 -- | Set the 'Spatial''s position. 56 -- | Set the spatial's position.
53 setPos :: Vector3 -> s -> s 57 setPos :: Vector3 -> s -> s
54 58
55 -- | Make the 'Spatial' look at the given point. 59 -- | Make the spatial look at the given point.
56 lookAt :: Vector3 -> s -> s 60 lookAt :: Vector3 -> s -> s
57 lookAt pt s = 61 lookAt pt s =
58 let position = pos s 62 let position = pos s
@@ -61,15 +65,15 @@ class Spatial3 s where
61 u = r `cross` fwd 65 u = r `cross` fwd
62 in 66 in
63 setTransform (M.transform r u (-fwd) position) s 67 setTransform (M.transform r u (-fwd) position) s
64 68
65 -- | Make the 'Spatial' orbit around the given point 69 -- | Make the spatial orbit around the given point
66 orbit :: Vector3 -- ^ Target point 70 orbit :: Vector3 -- ^ Target point
67 -> Float -- ^ Horizontal angle 71 -> Float -- ^ Horizontal angle
68 -> Float -- ^ Vertical angle 72 -> Float -- ^ Vertical angle
69 -> Float -- ^ Orbit radius. 73 -> Float -- ^ Orbit radius.
70 -> s 74 -> s
71 -> s 75 -> s
72 76
73 orbit pt anglex angley radius s = 77 orbit pt anglex angley radius s =
74 let ax = anglex * pi / 180 78 let ax = anglex * pi / 180
75 ay = angley * pi / 180 79 ay = angley * pi / 180
@@ -82,3 +86,59 @@ class Spatial3 s where
82 pz = (z pt) + radius*cx*cy 86 pz = (z pt) + radius*cx*cy
83 in 87 in
84 setPos (vec3 px py pz) s 88 setPos (vec3 px py pz) s
89
90-- | An object in 3D space.
91data Obj3 = Obj3
92 { r :: Vector3
93 , u :: Vector3
94 , f :: Vector3
95 , p :: Vector3
96 } deriving Show
97
98instance Spatial3 Obj3 where
99 move d o = o { p = p o + d }
100 moveFwd s o = o { p = p o + scale (-s) (f o) }
101 moveBack s o = o { p = p o + scale s (f o) }
102 strafeLeft s o = o { p = p o + scale (-s) (r o) }
103 strafeRight s o = o { p = p o + scale s (r o) }
104 pitch a o =
105 let a' = toRAD a
106 sa = sin a'
107 ca = cos a'
108 r' = normalise $ scale ca (r o) + scale sa (f o)
109 f' = normalise $ r' `cross` u o
110 in o { r = r', f = f' }
111 yaw a o =
112 let a' = toRAD a
113 sa = sin a'
114 ca = cos a'
115 f' = normalise $ scale ca (f o) + scale sa (u o)
116 u' = normalise $ r o `cross` f'
117 in o { u = u', f = f' }
118 roll a o =
119 let a' = toRAD a
120 sa = sin a'
121 ca = cos a'
122 u' = normalise $ scale ca (u o) - scale sa (r o)
123 f' = normalise $ f o `cross` u'
124 in o { u = u', f = f' }
125 pos = p
126 fwd = f
127 up = u
128 right = r
129 transform o = M.transform (r o) (u o) (f o) (p o)
130 setTransform t o = Obj3
131 { r = M.right t
132 , u = M.up t
133 , f = M.forward t
134 , p = M.position t
135 }
136 setPos pos o = o { p = pos }
137
138fromVectors :: Right3 -> Up3 -> Forward3 -> Position3 -> Obj3
139fromVectors = Obj3
140
141fromTransform :: Matrix4 -> Obj3
142fromTransform m = Obj3 (M.right m) (M.up m) (M.forward m) (M.position m)
143
144toRAD = (*pi) . (/180)
diff --git a/Spear/Scene/GameObject.hs b/Spear/Scene/GameObject.hs
index ecbe7a1..30211f4 100644
--- a/Spear/Scene/GameObject.hs
+++ b/Spear/Scene/GameObject.hs
@@ -39,6 +39,7 @@ import qualified Spear.Math.Matrix3 as M3
39import qualified Spear.Math.Matrix4 as M4 39import qualified Spear.Math.Matrix4 as M4
40import Spear.Math.MatrixUtils 40import Spear.Math.MatrixUtils
41import qualified Spear.Math.Spatial2 as S2 41import qualified Spear.Math.Spatial2 as S2
42import qualified Spear.Math.Spatial3 as S3
42import Spear.Math.Utils 43import Spear.Math.Utils
43import Spear.Math.Vector 44import Spear.Math.Vector
44import qualified Spear.Render.AnimatedModel as AM 45import qualified Spear.Render.AnimatedModel as AM
@@ -264,7 +265,7 @@ goRender sprog aprog cam go =
264 axis' = axis go 265 axis' = axis go
265 a = angle go 266 a = angle go
266 proj = Cam.projection cam 267 proj = Cam.projection cam
267 view = M4.inverseTransform $ Cam.transform cam 268 view = M4.inverseTransform $ S3.transform cam
268 transf = S2.transform go 269 transf = S2.transform go
269 normal = fastNormalMatrix modelview 270 normal = fastNormalMatrix modelview
270 modelview = case style of 271 modelview = case style of