diff options
| author | Jeanne-Kamikaze <jeannekamikaze@gmail.com> | 2013-03-12 20:03:56 +0100 |
|---|---|---|
| committer | Jeanne-Kamikaze <jeannekamikaze@gmail.com> | 2013-03-12 20:03:56 +0100 |
| commit | 4541db68038929e800637d92163b8adfc424c2fe (patch) | |
| tree | 3ccf00d1e1b644757eec9b957042ff60dd56f3f2 | |
| parent | 4f8f7d86b6cd9492c5af65a304eb638810e82e41 (diff) | |
Added Obj3
| -rw-r--r-- | Spear/App/Input.hs | 40 | ||||
| -rw-r--r-- | Spear/GL.hs | 3 | ||||
| -rw-r--r-- | Spear/Math/Camera.hs | 100 | ||||
| -rw-r--r-- | Spear/Math/MatrixUtils.hs | 9 | ||||
| -rw-r--r-- | Spear/Math/Spatial3.hs | 134 | ||||
| -rw-r--r-- | Spear/Scene/GameObject.hs | 3 |
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 | ) |
| 28 | where | 28 | where |
| 29 | 29 | ||
| 30 | |||
| 31 | import Data.Char (ord) | 30 | import Data.Char (ord) |
| 32 | import qualified Data.Vector.Unboxed as V | 31 | import qualified Data.Vector.Unboxed as V |
| 33 | import qualified Graphics.UI.GLFW as GLFW | 32 | import qualified Graphics.UI.GLFW as GLFW |
| 34 | import Graphics.Rendering.OpenGL.GL.CoordTrans | 33 | import Graphics.Rendering.OpenGL.GL.CoordTrans |
| 35 | import Data.StateVar | 34 | import Data.StateVar |
| 36 | 35 | ||
| 37 | |||
| 38 | data Key | 36 | data 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 | |||
| 49 | type Keyboard = Key -> Bool | 47 | type Keyboard = Key -> Bool |
| 50 | 48 | ||
| 51 | |||
| 52 | data MouseButton = LMB | RMB | MMB | 49 | data MouseButton = LMB | RMB | MMB |
| 53 | deriving (Enum, Bounded) | 50 | deriving (Enum, Bounded) |
| 54 | 51 | ||
| 55 | |||
| 56 | data MouseProp = MouseX | MouseY | MouseDX | MouseDY | 52 | data MouseProp = MouseX | MouseY | MouseDX | MouseDY |
| 57 | deriving Enum | 53 | deriving Enum |
| 58 | 54 | ||
| 59 | |||
| 60 | data Mouse = Mouse | 55 | data Mouse = Mouse |
| 61 | { button :: MouseButton -> Bool | 56 | { button :: MouseButton -> Bool |
| 62 | , property :: MouseProp -> Float | 57 | , property :: MouseProp -> Float |
| 63 | } | 58 | } |
| 64 | 59 | ||
| 65 | |||
| 66 | data Input = Input | 60 | data 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 | |||
| 79 | newKeyboard :: Keyboard | 72 | newKeyboard :: Keyboard |
| 80 | newKeyboard = const False | 73 | newKeyboard = const False |
| 81 | 74 | ||
| 82 | |||
| 83 | -- | Get the keyboard. | 75 | -- | Get the keyboard. |
| 84 | getKeyboard :: IO Keyboard | 76 | getKeyboard :: IO Keyboard |
| 85 | getKeyboard = | 77 | getKeyboard = |
| @@ -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 = | |||
| 101 | newMouse :: Mouse | 92 | newMouse :: Mouse |
| 102 | newMouse = Mouse (const False) (const 0) | 93 | newMouse = 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 | |||
| 109 | getMouse oldMouse = | 99 | getMouse 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. |
| 138 | newInput :: Input | 127 | newInput :: Input |
| 139 | newInput = Input newKeyboard newMouse | 128 | newInput = Input newKeyboard newMouse |
| 140 | 129 | ||
| 141 | |||
| 142 | -- | Get input devices. | 130 | -- | Get input devices. |
| 143 | getInput :: Input -> IO Input | 131 | getInput :: Input -> IO Input |
| 144 | getInput (Input _ oldMouse) = do | 132 | getInput (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. |
| 151 | pollInput :: IO () | 138 | pollInput :: IO () |
| 152 | pollInput = GLFW.pollEvents | 139 | pollInput = GLFW.pollEvents |
| 153 | 140 | ||
| 154 | |||
| 155 | -- | Return a mouse that reacts to button toggles. | 141 | -- | Return a mouse that reacts to button toggles. |
| 156 | toggledMouse :: Mouse -- ^ Previous mouse state. | 142 | toggledMouse :: 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 | ||
| 160 | toggledMouse prev cur = cur { button = \bt -> button cur bt && not (button prev bt) } | 146 | toggledMouse 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. |
| 164 | toggledKeyboard :: Keyboard -- ^ Previous keyboard state. | 149 | toggledKeyboard :: 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 | ||
| 168 | toggledKeyboard prev cur key = cur key && not (prev key) | 153 | toggledKeyboard 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. |
| 174 | type ButtonDelay = MouseButton -> Float | 156 | type 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 | |||
| 185 | newDM :: ButtonDelay -- ^ Delay configuration for each button. | 166 | newDM :: ButtonDelay -- ^ Delay configuration for each button. |
| 186 | -> DelayedMouse | 167 | -> DelayedMouse |
| 187 | newDM delay = DelayedMouse newMouse delay $ | 168 | newDM delay = DelayedMouse newMouse delay $ |
| 188 | V.replicate (fromEnum (maxBound :: MouseButton)) 0 | 169 | V.replicate (fromEnum (maxBound :: MouseButton)) 0 |
| 189 | 170 | ||
| 190 | |||
| 191 | updateDM :: DelayedMouse -- ^ Current mouse state. | 171 | updateDM :: 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 | |||
| 209 | toGLFWkey :: Key -> Int | 187 | toGLFWkey :: Key -> Int |
| 210 | toGLFWkey KEY_A = ord 'A' | 188 | toGLFWkey KEY_A = ord 'A' |
| 211 | toGLFWkey KEY_B = ord 'B' | 189 | toGLFWkey KEY_B = ord 'B' |
| @@ -257,6 +235,10 @@ toGLFWkey KEY_F11 = fromEnum GLFW.F11 | |||
| 257 | toGLFWkey KEY_F12 = fromEnum GLFW.F12 | 235 | toGLFWkey KEY_F12 = fromEnum GLFW.F12 |
| 258 | toGLFWkey KEY_ESC = fromEnum GLFW.ESC | 236 | toGLFWkey KEY_ESC = fromEnum GLFW.ESC |
| 259 | toGLFWkey KEY_SPACE = ord ' ' | 237 | toGLFWkey KEY_SPACE = ord ' ' |
| 238 | toGLFWkey KEY_UP = fromEnum GLFW.UP | ||
| 239 | toGLFWkey KEY_DOWN = fromEnum GLFW.DOWN | ||
| 240 | toGLFWkey KEY_LEFT = fromEnum GLFW.LEFT | ||
| 241 | toGLFWkey KEY_RIGHT = fromEnum GLFW.RIGHT | ||
| 260 | 242 | ||
| 261 | 243 | ||
| 262 | toGLFWbutton :: MouseButton -> GLFW.MouseButton | 244 | toGLFWbutton :: 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 () |
| 454 | attribVAOPointer idx ncomp dattype normalise stride off = | 454 | attribVAOPointer 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. |
| 458 | drawArrays | 459 | drawArrays |
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 @@ | |||
| 1 | module Spear.Math.Camera | 1 | module 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 | ) | ||
| 2 | where | 14 | where |
| 3 | 15 | ||
| 4 | 16 | ||
| 5 | import qualified Spear.Math.Matrix4 as M | 17 | import qualified Spear.Math.Matrix4 as M |
| 6 | import qualified Spear.Math.Spatial3 as S | 18 | import Spear.Math.Spatial3 |
| 7 | import Spear.Math.Vector | 19 | import Spear.Math.Vector |
| 8 | 20 | ||
| 9 | 21 | ||
| 10 | data Camera = Camera | 22 | data 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 | ||
| 27 | type Fovy = Float | ||
| 28 | type Aspect = Float | ||
| 29 | type Near = Float | ||
| 30 | type Far = Float | ||
| 31 | type Left = Float | ||
| 32 | type Right = Float | ||
| 33 | type Bottom = Float | ||
| 34 | type Top = Float | ||
| 15 | 35 | ||
| 16 | -- | Build a perspective camera. | 36 | -- | Build a perspective camera. |
| 17 | perspective :: Float -- ^ Fovy - Vertical field of view angle in degrees. | 37 | perspective :: 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 | ||
| 27 | perspective fovy r n f right up fwd pos = | 47 | perspective 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. |
| 35 | ortho :: Float -- ^ Left. | 55 | ortho :: 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 | ||
| 47 | ortho l r b t n f right up fwd pos = | 67 | ortho 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 | ||
| 54 | instance S.Spatial3 Camera where | 74 | instance 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 | |||
| 15 | import Spear.Math.Camera as Cam | 15 | import Spear.Math.Camera as Cam |
| 16 | import Spear.Math.Matrix3 as M3 | 16 | import Spear.Math.Matrix3 as M3 |
| 17 | import Spear.Math.Matrix4 as M4 | 17 | import Spear.Math.Matrix4 as M4 |
| 18 | import Spear.Math.Spatial3 as S | ||
| 18 | import Spear.Math.Vector as V | 19 | import 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. |
| 137 | pltInverse :: Matrix3 -> Matrix4 | 138 | pltInverse :: Matrix3 -> Matrix4 |
| 138 | pltInverse = M4.inverseTransform . pltTransform | 139 | pltInverse = M4.inverseTransform . pltTransform |
| @@ -142,7 +143,7 @@ pltInverse = M4.inverseTransform . pltTransform | |||
| 142 | objToClip :: Camera -> Matrix4 -> Vector3 -> Vector2 | 143 | objToClip :: Camera -> Matrix4 -> Vector3 -> Vector2 |
| 143 | objToClip cam model p = | 144 | objToClip 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 @@ | |||
| 1 | module Spear.Math.Spatial3 | 1 | module Spear.Math.Spatial3 |
| 2 | ( | ||
| 3 | Spatial3(..) | ||
| 4 | , Obj3 | ||
| 5 | , fromVectors | ||
| 6 | , fromTransform | ||
| 7 | ) | ||
| 2 | where | 8 | where |
| 3 | 9 | ||
| 4 | |||
| 5 | import Spear.Math.Vector | 10 | import Spear.Math.Vector |
| 6 | import Spear.Math.Matrix4 as M | 11 | import Spear.Math.Matrix4 as M hiding (scale) |
| 7 | |||
| 8 | 12 | ||
| 9 | class Spatial3 s where | 13 | class 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. | ||
| 91 | data Obj3 = Obj3 | ||
| 92 | { r :: Vector3 | ||
| 93 | , u :: Vector3 | ||
| 94 | , f :: Vector3 | ||
| 95 | , p :: Vector3 | ||
| 96 | } deriving Show | ||
| 97 | |||
| 98 | instance 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 | |||
| 138 | fromVectors :: Right3 -> Up3 -> Forward3 -> Position3 -> Obj3 | ||
| 139 | fromVectors = Obj3 | ||
| 140 | |||
| 141 | fromTransform :: Matrix4 -> Obj3 | ||
| 142 | fromTransform m = Obj3 (M.right m) (M.up m) (M.forward m) (M.position m) | ||
| 143 | |||
| 144 | toRAD = (*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 | |||
| 39 | import qualified Spear.Math.Matrix4 as M4 | 39 | import qualified Spear.Math.Matrix4 as M4 |
| 40 | import Spear.Math.MatrixUtils | 40 | import Spear.Math.MatrixUtils |
| 41 | import qualified Spear.Math.Spatial2 as S2 | 41 | import qualified Spear.Math.Spatial2 as S2 |
| 42 | import qualified Spear.Math.Spatial3 as S3 | ||
| 42 | import Spear.Math.Utils | 43 | import Spear.Math.Utils |
| 43 | import Spear.Math.Vector | 44 | import Spear.Math.Vector |
| 44 | import qualified Spear.Render.AnimatedModel as AM | 45 | import 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 |
