1 module prova.math.vector4;
2 
3 import prova.math,
4        std.math;
5 
6 ///
7 struct Vector4
8 {
9   ///
10   float x = 0;
11   ///
12   float y = 0;
13   ///
14   float z = 0;
15   ///
16   float w = 0;
17 
18   ///
19   this(float x, float y, float z, float w)
20   {
21     set(x, y, z, w);
22   }
23 
24   ///
25   this(Vector3 vector)
26   {
27     set(vector.x, vector.y, vector.z, 0);
28   }
29 
30   ///
31   this(Vector2 vector)
32   {
33     set(vector.x, vector.y, 0, 0);
34   }
35 
36   /// Sets the values of x, y, z, and w in a single statement
37   void set(float x, float y, float z, float w)
38   {
39     this.x = x;
40     this.y = y;
41     this.z = z;
42     this.w = w;
43   }
44 
45   /// Creates a normalized vector with a random direction
46   static Vector4 random()
47   {
48     Vector4 vector = Vector4(
49       randomF(1),
50       randomF(1),
51       randomF(1),
52       randomF(1)
53     );
54 
55     vector.normalize();
56 
57     return vector;
58   }
59 
60   /// Returns a normalized copy of this vector
61   Vector4 getNormalized() const
62   {
63     const float magnitude = getMagnitude();
64 
65     Vector4 result;
66     
67     if(magnitude != 0) {
68       result.x = x / magnitude;
69       result.y = y / magnitude;
70       result.z = z / magnitude;
71       result.w = w / magnitude;
72     }
73     
74     return result;
75   }
76 
77   /// Normalizes the vector
78   void normalize()
79   {
80     const float magnitude = getMagnitude();
81 
82     if(magnitude == 0)
83       return;
84 
85     x = x / magnitude;
86     y = y / magnitude;
87     z = z / magnitude;
88     w = w / magnitude;
89   }
90 
91   /// Returns the magnitude of the vector
92   float getMagnitude() const
93   {
94     return sqrt(x * x + y * y + z * z + w * w);
95   }
96 
97   /**
98    * Sets the magnitude of this vector
99    *
100    * If the previous magnitude is zero, the x value
101    * of the vector will be set to the magnitude
102    */
103   void setMagnitude(float magnitude)
104   {
105     if(getMagnitude() == 0) {
106       x = magnitude;
107       return;
108     }
109 
110     normalize();
111 
112     x *= magnitude;
113     y *= magnitude;
114     z *= magnitude;
115     w *= magnitude;
116   }
117 
118   /// Returns the distance between the vectors
119   float distanceTo(Vector4 vector) const
120   {
121     const float a = vector.x - x;
122     const float b = vector.y - y;
123     const float c = vector.z - z;
124     const float d = vector.w - w;
125 
126     return sqrt(a * a + b * b + c * c + d * d);
127   }
128 
129   /// Returns the squared distance between the vectors
130   float distanceToSquared(Vector4 vector) const
131   {
132     const float a = vector.x - x;
133     const float b = vector.y - y;
134     const float c = vector.z - z;
135     const float d = vector.w - w;
136 
137     return a * a + b * b + c * c + d * d;
138   }
139 
140   // Returns the dot product of the two vectors
141   float dot(Vector4 vector)
142   {
143     return x * vector.x + y * vector.y + z * vector.z + w * vector.w;
144   }
145 
146 
147   // assignment overloading
148   Vector4 opAddAssign(Vector4 vector)
149   {
150     x += vector.x;
151     y += vector.y;
152     z += vector.z;
153     w += vector.w;
154 
155     return this;
156   }
157 
158   Vector4 opSubAssign(Vector4 vector)
159   {
160     x -= vector.x;
161     y -= vector.y;
162     z -= vector.z;
163     w -= vector.w;
164 
165     return this;
166   }
167 
168   Vector4 opMulAssign(float a)
169   {
170     x *= a;
171     y *= a;
172     z *= a;
173     w *= a;
174 
175     return this;
176   }
177 
178   Vector4 opDivAssign(float a)
179   {
180     x /= a;
181     y /= a;
182     z /= a;
183     w /= a;
184 
185     return this;
186   }
187 
188 
189   // arithmetic overloading
190   Vector4 opAdd(Vector4 vector) const
191   {
192     Vector4 result;
193     result.x = x + vector.x;
194     result.y = y + vector.y;
195     result.z = z + vector.z;
196     result.w = w + vector.w;
197 
198     return result;
199   }
200 
201   Vector4 opSub(Vector4 vector) const
202   {
203     Vector4 result;
204     result.x = x - vector.x;
205     result.y = y - vector.y;
206     result.z = z - vector.z;
207     result.w = w - vector.w;
208 
209     return result; 
210   }
211 
212   Vector4 opUnary(string s)() const if (s == "-")
213   {
214     Vector4 result;
215     result.x = -x;
216     result.y = -y;
217     result.z = -z;
218     result.w = -w;
219 
220     return result;
221   }
222 
223   Vector4 opMul(float a) const
224   {
225     Vector4 result;
226     result.x = x * a;
227     result.y = y * a;
228     result.z = z * a;
229     result.w = w * a;
230 
231     return result; 
232   }
233 
234   Vector4 opDiv(float a) const
235   {
236     Vector4 result;
237     result.x = x / a;
238     result.y = y / a;
239     result.z = z / a;
240     result.w = w / a;
241 
242     return result; 
243   }
244 
245   void opAssign(Vector2 vector)
246   {
247     x = vector.x;
248     y = vector.y;
249     z = 0;
250     w = 0;
251   }
252 
253   void opAssign(Vector3 vector)
254   {
255     x = vector.x;
256     y = vector.y;
257     z = vector.z;
258     w = 0;
259   }
260 }