aboutsummaryrefslogtreecommitdiff
path: root/Spear/Math/Vector/Vector3.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Spear/Math/Vector/Vector3.hs')
-rw-r--r--Spear/Math/Vector/Vector3.hs165
1 files changed, 165 insertions, 0 deletions
diff --git a/Spear/Math/Vector/Vector3.hs b/Spear/Math/Vector/Vector3.hs
new file mode 100644
index 0000000..c19b7c7
--- /dev/null
+++ b/Spear/Math/Vector/Vector3.hs
@@ -0,0 +1,165 @@
1module Spear.Math.Vector.Vector3
2(
3 Vector3
4 -- * Construction
5, unitx3
6, unity3
7, unitz3
8, zero3
9, vec3
10, orbit
11 -- * Operations
12, cross
13)
14where
15
16
17import Spear.Math.Vector.Class
18
19import Foreign.C.Types (CFloat)
20import Foreign.Storable
21
22
23-- | Represents a vector in 3D.
24data Vector3 = Vector3
25 {-# UNPACK #-} !Float
26 {-# UNPACK #-} !Float
27 {-# UNPACK #-} !Float
28 deriving (Eq, Show)
29
30
31instance Num Vector3 where
32 Vector3 ax ay az + Vector3 bx by bz = Vector3 (ax + bx) (ay + by) (az + bz)
33 Vector3 ax ay az - Vector3 bx by bz = Vector3 (ax - bx) (ay - by) (az - bz)
34 Vector3 ax ay az * Vector3 bx by bz = Vector3 (ax * bx) (ay * by) (az * bz)
35 abs (Vector3 ax ay az) = Vector3 (abs ax) (abs ay) (abs az)
36 signum (Vector3 ax ay az) = Vector3 (signum ax) (signum ay) (signum az)
37 fromInteger i = Vector3 i' i' i' where i' = fromInteger i
38
39
40instance Fractional Vector3 where
41 Vector3 ax ay az / Vector3 bx by bz = Vector3 (ax / bx) (ay / by) (az / bz)
42 fromRational r = Vector3 r' r' r' where r' = fromRational r
43
44
45instance Ord Vector3 where
46 Vector3 ax ay az <= Vector3 bx by bz
47 = (ax <= bx)
48 || (az == bx && ay <= by)
49 || (ax == bx && ay == by && az <= bz)
50
51 Vector3 ax ay az >= Vector3 bx by bz
52 = (ax >= bx)
53 || (ax == bx && ay >= by)
54 || (ax == bx && ay == by && az >= bz)
55
56 Vector3 ax ay az < Vector3 bx by bz
57 = (ax < bx)
58 || (az == bx && ay < by)
59 || (ax == bx && ay == by && az < bz)
60
61 Vector3 ax ay az > Vector3 bx by bz
62 = (ax > bx)
63 || (ax == bx && ay > by)
64 || (ax == bx && ay == by && az > bz)
65
66 max (Vector3 ax ay az) (Vector3 bx by bz) = Vector3 (Prelude.max ax bx) (Prelude.max ay by) (Prelude.max az bz)
67
68 min (Vector3 ax ay az) (Vector3 bx by bz) = Vector3 (Prelude.min ax bx) (Prelude.min ay by) (Prelude.min az bz)
69
70
71instance VectorClass Vector3 where
72 fromList (ax:ay:az:_) = Vector3 ax ay az
73
74 x (Vector3 ax _ _ ) = ax
75
76 y (Vector3 _ ay _ ) = ay
77
78 z (Vector3 _ _ az) = az
79
80 (Vector3 ax _ _) ! 0 = ax
81 (Vector3 _ ay _) ! 1 = ay
82 (Vector3 _ _ az) ! 2 = az
83 _ ! _ = 0
84
85 Vector3 ax ay az `dot` Vector3 bx by bz = ax*bx + ay*by + az*bz
86
87 normSq (Vector3 ax ay az) = ax*ax + ay*ay + az*az
88
89 norm = sqrt . normSq
90
91 scale s (Vector3 ax ay az) = Vector3 (s*ax) (s*ay) (s*az)
92
93 neg (Vector3 ax ay az) = Vector3 (-ax) (-ay) (-az)
94
95 normalise v =
96 let n' = norm v
97 n = if n' == 0 then 1 else n'
98 in scale (1.0 / n) v
99
100
101sizeFloat = sizeOf (undefined :: CFloat)
102
103
104instance Storable Vector3 where
105 sizeOf _ = 3*sizeFloat
106 alignment _ = alignment (undefined :: CFloat)
107
108 peek ptr = do
109 ax <- peekByteOff ptr 0
110 ay <- peekByteOff ptr $ 1*sizeFloat
111 az <- peekByteOff ptr $ 2*sizeFloat
112 return (Vector3 ax ay az)
113
114 poke ptr (Vector3 ax ay az) = do
115 pokeByteOff ptr 0 ax
116 pokeByteOff ptr (1*sizeFloat) ay
117 pokeByteOff ptr (2*sizeFloat) az
118
119
120-- | Unit vector along the X axis.
121unitx3 = Vector3 1 0 0
122
123
124-- | Unit vector along the Y axis.
125unity3 = Vector3 0 1 0
126
127
128-- | Unit vector along the Z axis.
129unitz3 = Vector3 0 0 1
130
131
132-- | Zero vector.
133zero3 = Vector3 0 0 0
134
135
136-- | Create a 3D vector from the given values.
137vec3 :: Float -> Float -> Float -> Vector3
138vec3 ax ay az = Vector3 ax ay az
139
140
141-- | Create a 3D vector as a point on a sphere.
142orbit :: Vector3 -- ^ Sphere center.
143 -> Float -- ^ Sphere radius
144 -> Float -- ^ Azimuth angle.
145 -> Float -- ^ Zenith angle.
146 -> Vector3
147
148orbit center radius anglex angley =
149 let ax = anglex * pi / 180
150 ay = angley * pi / 180
151 sx = sin ax
152 sy = sin ay
153 cx = cos ax
154 cy = cos ay
155 px = x center + radius*cy*sx
156 py = y center + radius*sy
157 pz = z center + radius*cx*cy
158 in
159 vec3 px py pz
160
161
162-- | Compute the given vectors' cross product.
163cross :: Vector3 -> Vector3 -> Vector3
164(Vector3 ax ay az) `cross` (Vector3 bx by bz) =
165 Vector3 (ay * bz - az * by) (az * bx - ax * bz) (ax * by - ay * bx)