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(float a)
179   {
180     x *= a;
181     y *= a;
182     z *= a;
183 
184     return this;
185   }
186 
187   Vector3 opDivAssign(float a)
188   {
189     x /= a;
190     y /= a;
191     z /= a;
192 
193     return this;
194   }
195 
196 
197   // arithmetic overloading
198   Vector3 opAdd(Vector3 vector) const
199   {
200     Vector3 result;
201     result.x = x + vector.x;
202     result.y = y + vector.y;
203     result.z = z + vector.z;
204 
205     return result;
206   }
207 
208   Vector3 opAdd(Vector2 vector) const
209   {
210     Vector3 result;
211     result.x = x + vector.x;
212     result.y = y + vector.y;
213     result.z = z;
214 
215     return result; 
216   }
217 
218   Vector3 opSub(Vector3 vector) const
219   {
220     Vector3 result;
221     result.x = x - vector.x;
222     result.y = y - vector.y;
223     result.z = z - vector.z;
224 
225     return result; 
226   }
227 
228   Vector3 opSub(Vector2 vector) const
229   {
230     Vector3 result;
231     result.x = x - vector.x;
232     result.y = y - vector.y;
233     result.z = z;
234 
235     return result; 
236   }
237 
238   Vector3 opUnary(string s)() const if (s == "-")
239   {
240     Vector3 result;
241     result.x = -x;
242     result.y = -y;
243     result.z = -z;
244 
245     return result;
246   }
247 
248   Vector3 opMul(float a) const
249   {
250     Vector3 result;
251     result.x = x * a;
252     result.y = y * a;
253     result.z = z * a;
254 
255     return result; 
256   }
257 
258   Vector3 opDiv(float a) const
259   {
260     Vector3 result;
261     result.x = x / a;
262     result.y = y / a;
263     result.z = z / a;
264 
265     return result; 
266   }
267 
268   void opAssign(Vector2 vector)
269   {
270     x = vector.x;
271     y = vector.y;
272     z = 0;
273   }
274 }