diff options
Diffstat (limited to 'Spear/Math/Vector/Vector3.hs')
-rw-r--r-- | Spear/Math/Vector/Vector3.hs | 165 |
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 @@ | |||
1 | module 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 | ) | ||
14 | where | ||
15 | |||
16 | |||
17 | import Spear.Math.Vector.Class | ||
18 | |||
19 | import Foreign.C.Types (CFloat) | ||
20 | import Foreign.Storable | ||
21 | |||
22 | |||
23 | -- | Represents a vector in 3D. | ||
24 | data Vector3 = Vector3 | ||
25 | {-# UNPACK #-} !Float | ||
26 | {-# UNPACK #-} !Float | ||
27 | {-# UNPACK #-} !Float | ||
28 | deriving (Eq, Show) | ||
29 | |||
30 | |||
31 | instance 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 | |||
40 | instance 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 | |||
45 | instance 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 | |||
71 | instance 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 | |||
101 | sizeFloat = sizeOf (undefined :: CFloat) | ||
102 | |||
103 | |||
104 | instance 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. | ||
121 | unitx3 = Vector3 1 0 0 | ||
122 | |||
123 | |||
124 | -- | Unit vector along the Y axis. | ||
125 | unity3 = Vector3 0 1 0 | ||
126 | |||
127 | |||
128 | -- | Unit vector along the Z axis. | ||
129 | unitz3 = Vector3 0 0 1 | ||
130 | |||
131 | |||
132 | -- | Zero vector. | ||
133 | zero3 = Vector3 0 0 0 | ||
134 | |||
135 | |||
136 | -- | Create a 3D vector from the given values. | ||
137 | vec3 :: Float -> Float -> Float -> Vector3 | ||
138 | vec3 ax ay az = Vector3 ax ay az | ||
139 | |||
140 | |||
141 | -- | Create a 3D vector as a point on a sphere. | ||
142 | orbit :: Vector3 -- ^ Sphere center. | ||
143 | -> Float -- ^ Sphere radius | ||
144 | -> Float -- ^ Azimuth angle. | ||
145 | -> Float -- ^ Zenith angle. | ||
146 | -> Vector3 | ||
147 | |||
148 | orbit 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. | ||
163 | cross :: 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) | ||