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