aboutsummaryrefslogtreecommitdiff
path: root/Spear/Math/MatrixUtils.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Spear/Math/MatrixUtils.hs')
-rw-r--r--Spear/Math/MatrixUtils.hs300
1 files changed, 150 insertions, 150 deletions
diff --git a/Spear/Math/MatrixUtils.hs b/Spear/Math/MatrixUtils.hs
index e4273a1..24d9778 100644
--- a/Spear/Math/MatrixUtils.hs
+++ b/Spear/Math/MatrixUtils.hs
@@ -1,150 +1,150 @@
1module Spear.Math.MatrixUtils 1module Spear.Math.MatrixUtils
2( 2(
3 fastNormalMatrix 3 fastNormalMatrix
4, unproject 4, unproject
5, rpgUnproject 5, rpgUnproject
6, rpgTransform 6, rpgTransform
7, pltTransform 7, pltTransform
8, rpgInverse 8, rpgInverse
9, pltInverse 9, pltInverse
10, objToClip 10, objToClip
11) 11)
12where 12where
13 13
14 14
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.Spatial3 as S
19import Spear.Math.Vector as V 19import Spear.Math.Vector as V
20 20
21 21
22-- | Compute the normal matrix of the given matrix. 22-- | Compute the normal matrix of the given matrix.
23fastNormalMatrix :: Matrix4 -> Matrix3 23fastNormalMatrix :: Matrix4 -> Matrix3
24fastNormalMatrix m = 24fastNormalMatrix m =
25 let m' = M4.transpose . M4.inverseTransform $ m 25 let m' = M4.transpose . M4.inverseTransform $ m
26 in M3.mat3 26 in M3.mat3
27 (M4.m00 m') (M4.m10 m') (M4.m20 m') 27 (M4.m00 m') (M4.m10 m') (M4.m20 m')
28 (M4.m01 m') (M4.m11 m') (M4.m21 m') 28 (M4.m01 m') (M4.m11 m') (M4.m21 m')
29 (M4.m02 m') (M4.m12 m') (M4.m22 m') 29 (M4.m02 m') (M4.m12 m') (M4.m22 m')
30 30
31 31
32-- | Transform the given point in window coordinates to object coordinates. 32-- | Transform the given point in window coordinates to object coordinates.
33unproject :: Matrix4 -- ^ Inverse projection matrix 33unproject :: Matrix4 -- ^ Inverse projection matrix
34 -> Matrix4 -- ^ Inverse modelview matrix. 34 -> Matrix4 -- ^ Inverse modelview matrix.
35 -> Float -- ^ Viewport x 35 -> Float -- ^ Viewport x
36 -> Float -- ^ Viewport y 36 -> Float -- ^ Viewport y
37 -> Float -- ^ Viewport width 37 -> Float -- ^ Viewport width
38 -> Float -- ^ Viewport height 38 -> Float -- ^ Viewport height
39 -> Float -- ^ Window x 39 -> Float -- ^ Window x
40 -> Float -- ^ Window y 40 -> Float -- ^ Window y
41 -> Float -- ^ Window z 41 -> Float -- ^ Window z
42 -> Vector3 42 -> Vector3
43unproject projI modelviewI vpx vpy w h x y z = 43unproject projI modelviewI vpx vpy w h x y z =
44 let 44 let
45 xmouse = 2*(x-vpx)/w - 1 45 xmouse = 2*(x-vpx)/w - 1
46 ymouse = 2*(y-vpy)/h - 1 46 ymouse = 2*(y-vpy)/h - 1
47 zmouse = 2*z - 1 47 zmouse = 2*z - 1
48 in 48 in
49 (modelviewI * projI) `M4.mulp` vec3 xmouse ymouse zmouse 49 (modelviewI * projI) `M4.mulp` vec3 xmouse ymouse zmouse
50 50
51 51
52-- | Transform the given point in window coordinates to 2d coordinates. 52-- | Transform the given point in window coordinates to 2d coordinates.
53-- 53--
54-- The line defined by the given point in window space is intersected with 54-- The line defined by the given point in window space is intersected with
55-- the XZ plane in world space to yield the resulting 2d point. 55-- the XZ plane in world space to yield the resulting 2d point.
56rpgUnproject 56rpgUnproject
57 :: Matrix4 -- ^ Inverse projection matrix 57 :: Matrix4 -- ^ Inverse projection matrix
58 -> Matrix4 -- ^ Inverse viewI matrix. 58 -> Matrix4 -- ^ Inverse viewI matrix.
59 -> Float -- ^ Viewport x 59 -> Float -- ^ Viewport x
60 -> Float -- ^ Viewport y 60 -> Float -- ^ Viewport y
61 -> Float -- ^ Viewport width 61 -> Float -- ^ Viewport width
62 -> Float -- ^ Viewport height 62 -> Float -- ^ Viewport height
63 -> Float -- ^ Window x 63 -> Float -- ^ Window x
64 -> Float -- ^ Window y 64 -> Float -- ^ Window y
65 -> Vector2 65 -> Vector2
66rpgUnproject projI viewI vpx vpy w h wx wy = 66rpgUnproject projI viewI vpx vpy w h wx wy =
67 let 67 let
68 p1 = unproject projI viewI vpx vpy w h wx wy 0 68 p1 = unproject projI viewI vpx vpy w h wx wy 0
69 p2 = unproject projI viewI vpx vpy w h wx wy (-1) 69 p2 = unproject projI viewI vpx vpy w h wx wy (-1)
70 lambda = (y p1 / (y p1 - y p2)) 70 lambda = (y p1 / (y p1 - y p2))
71 p' = p1 + V.scale lambda (p2 - p1) 71 p' = p1 + V.scale lambda (p2 - p1)
72 in 72 in
73 vec2 (x p') (-(z p')) 73 vec2 (x p') (-(z p'))
74 74
75 75
76-- | Map an object's transform in view space to world space. 76-- | Map an object's transform in view space to world space.
77rpgTransform 77rpgTransform
78 :: Float -- ^ The height above the ground 78 :: Float -- ^ The height above the ground
79 -> Float -- ^ Angle of rotation 79 -> Float -- ^ Angle of rotation
80 -> Vector3 -- ^ Axis of rotation 80 -> Vector3 -- ^ Axis of rotation
81 -> Vector2 -- ^ Object's position 81 -> Vector2 -- ^ Object's position
82 -> Matrix4 -- ^ Inverse view matrix 82 -> Matrix4 -- ^ Inverse view matrix
83 -> Matrix4 83 -> Matrix4
84rpgTransform h a axis pos viewI = 84rpgTransform h a axis pos viewI =
85 let p1 = viewI `M4.mulp` (vec3 (x pos) (y pos) 0) 85 let p1 = viewI `M4.mulp` (vec3 (x pos) (y pos) 0)
86 p2 = viewI `M4.mulp` (vec3 (x pos) (y pos) (-1)) 86 p2 = viewI `M4.mulp` (vec3 (x pos) (y pos) (-1))
87 lambda = (y p1 / (y p1 - y p2)) 87 lambda = (y p1 / (y p1 - y p2))
88 p = p1 + V.scale lambda (p2 - p1) 88 p = p1 + V.scale lambda (p2 - p1)
89 mat' = axisAngle axis a 89 mat' = axisAngle axis a
90 r = M4.right mat' 90 r = M4.right mat'
91 u = M4.up mat' 91 u = M4.up mat'
92 f = M4.forward mat' 92 f = M4.forward mat'
93 t = p + vec3 0 h 0 93 t = p + vec3 0 h 0
94 in mat4 94 in mat4
95 (x r) (x u) (x f) (x t) 95 (x r) (x u) (x f) (x t)
96 (y r) (y u) (y f) (y t) 96 (y r) (y u) (y f) (y t)
97 (z r) (z u) (z f) (z t) 97 (z r) (z u) (z f) (z t)
98 0 0 0 1 98 0 0 0 1
99 99
100 100
101-- | Map an object's transform in view space to world space. 101-- | Map an object's transform in view space to world space.
102pltTransform :: Matrix3 -> Matrix4 102pltTransform :: Matrix3 -> Matrix4
103pltTransform mat = 103pltTransform mat =
104 let r = let r' = M3.right mat in vec3 (x r') (y r') 0 104 let r = let r' = M3.right mat in vec3 (x r') (y r') 0
105 u = let u' = M3.up mat in vec3 (x u') (y u') 0 105 u = let u' = M3.up mat in vec3 (x u') (y u') 0
106 f = unitz3 106 f = unitz3
107 t = let t' = M3.position mat in vec3 (x t') (y t') 0 107 t = let t' = M3.position mat in vec3 (x t') (y t') 0
108 in mat4 108 in mat4
109 (x r) (x u) (x f) (x t) 109 (x r) (x u) (x f) (x t)
110 (y r) (y u) (y f) (y t) 110 (y r) (y u) (y f) (y t)
111 (z r) (z u) (z f) (z t) 111 (z r) (z u) (z f) (z t)
112 0 0 0 1 112 0 0 0 1
113 113
114 114
115-- | Map an object's transform in world space to view space. 115-- | Map an object's transform in world space to view space.
116-- 116--
117-- 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.
118-- 118--
119-- Use this in games such as RPGs and RTSs. 119-- Use this in games such as RPGs and RTSs.
120rpgInverse 120rpgInverse
121 :: Float -- ^ The height above the ground 121 :: Float -- ^ The height above the ground
122 -> Float -- ^ Angle of rotation 122 -> Float -- ^ Angle of rotation
123 -> Vector3 -- ^ Axis of rotation 123 -> Vector3 -- ^ Axis of rotation
124 -> Vector2 -- ^ Object's position 124 -> Vector2 -- ^ Object's position
125 -> Matrix4 -- ^ Inverse view matrix 125 -> Matrix4 -- ^ Inverse view matrix
126 -> Matrix4 126 -> Matrix4
127rpgInverse h a axis pos viewI = 127rpgInverse h a axis pos viewI =
128 M4.inverseTransform $ rpgTransform h a axis pos viewI 128 M4.inverseTransform $ rpgTransform h a axis pos viewI
129 129
130 130
131-- | Map an object's transform in world space to view space. 131-- | Map an object's transform in world space to view space.
132-- 132--
133-- 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.
134-- 134--
135-- 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.
136-- 136--
137-- Use this in games like platformers and space invaders style games. 137-- Use this in games like platformers and space invaders style games.
138pltInverse :: Matrix3 -> Matrix4 138pltInverse :: Matrix3 -> Matrix4
139pltInverse = M4.inverseTransform . pltTransform 139pltInverse = M4.inverseTransform . pltTransform
140 140
141 141
142-- | Transform an object from object to clip space coordinates. 142-- | Transform an object from object to clip space coordinates.
143objToClip :: Camera -> Matrix4 -> Vector3 -> Vector2 143objToClip :: Camera -> Matrix4 -> Vector3 -> Vector2
144objToClip cam model p = 144objToClip cam model p =
145 let 145 let
146 view = M4.inverseTransform $ S.transform cam 146 view = M4.inverseTransform $ S.transform cam
147 proj = Cam.projection cam 147 proj = Cam.projection cam
148 p' = (proj * view * model) `M4.mulp` p 148 p' = (proj * view * model) `M4.mulp` p
149 in 149 in
150 vec2 (x p') (y p') 150 vec2 (x p') (y p')