1 #pragma once
2 
3 /* greebo: This file contains the templated class definition of the three-component vector
4  *
5  * BasicVector4: A vector with three components of type <Element>
6  *
7  * The BasicVector4 is equipped with the most important operators like *, *= and so on.
8  *
9  * Note: The most commonly used Vector4 is a BasicVector4<float>, this is also defined in this file
10  *
11  * Note: that the multiplication of a Vector4 with another one (Vector4*Vector4) does NOT
12  * result in an inner product but in a component-wise scaling. Use the .dot() method to
13  * execute an inner product of two vectors.
14  */
15 
16 #include "FloatTools.h"
17 #include "Vector3.h"
18 
19 // A 4-element vector of type <Element>
20 template<typename Element>
21 class BasicVector4
22 {
23 
24 		// The components of this vector
25 		Element m_elements[4];
26 
27 	public:
28 
29 		// Constructor (no arguments)
BasicVector4()30 		BasicVector4 ()
31 		{
32 		}
33 
34 		// Construct a BasicVector4 out of the 4 arguments
BasicVector4(Element x_,Element y_,Element z_,Element w_)35 		BasicVector4 (Element x_, Element y_, Element z_, Element w_)
36 		{
37 			x() = x_;
38 			y() = y_;
39 			z() = z_;
40 			w() = w_;
41 		}
42 
43 		// Construct a BasicVector4 out of a Vector3 plus a fourth argument
BasicVector4(const BasicVector3<Element> & self,Element w_)44 		BasicVector4 (const BasicVector3<Element>& self, Element w_)
45 		{
46 			x() = self.x();
47 			y() = self.y();
48 			z() = self.z();
49 			w() = w_;
50 		}
51 
52 		/** Set all 4 components to the provided values.
53 		 */
set(const Element & x,const Element & y,const Element & z,const Element & a)54 		void set (const Element& x, const Element& y, const Element& z, const Element& a)
55 		{
56 			m_elements[0] = x;
57 			m_elements[1] = y;
58 			m_elements[2] = z;
59 			m_elements[3] = a;
60 		}
61 
62 		// Return non-constant references to the components
x()63 		Element& x ()
64 		{
65 			return m_elements[0];
66 		}
y()67 		Element& y ()
68 		{
69 			return m_elements[1];
70 		}
z()71 		Element& z ()
72 		{
73 			return m_elements[2];
74 		}
w()75 		Element& w ()
76 		{
77 			return m_elements[3];
78 		}
79 
80 		// Return constant references to the components
x()81 		const Element& x () const
82 		{
83 			return m_elements[0];
84 		}
y()85 		const Element& y () const
86 		{
87 			return m_elements[1];
88 		}
z()89 		const Element& z () const
90 		{
91 			return m_elements[2];
92 		}
w()93 		const Element& w () const
94 		{
95 			return m_elements[3];
96 		}
97 
index(std::size_t i)98 		Element index (std::size_t i) const
99 		{
100 			return m_elements[i];
101 		}
index(std::size_t i)102 		Element& index (std::size_t i)
103 		{
104 			return m_elements[i];
105 		}
106 
107 		/** Compare this BasicVector4 against another for equality.
108 		 */
109 		bool operator== (const BasicVector4& other) const
110 		{
111 			return (other.x() == x() && other.y() == y() && other.z() == z() && other.w() == w());
112 		}
113 
114 		/** Compare this BasicVector4 against another for inequality.
115 		 */
116 		bool operator!= (const BasicVector4& other) const
117 		{
118 			return !(*this == other);
119 		}
120 
121 		/*	Define the addition operators + and += with any other BasicVector4 of type OtherElement
122 		 *  The vectors are added to each other element-wise
123 		 */
124 		template<typename OtherElement>
125 		BasicVector4<Element> operator+ (const BasicVector4<OtherElement>& other) const
126 		{
127 			return BasicVector4<Element> (m_elements[0] + static_cast<Element> (other.x()), m_elements[1]
128 					+ static_cast<Element> (other.y()), m_elements[2] + static_cast<Element> (other.z()), m_elements[3]
129 					+ static_cast<Element> (other.w()));
130 		}
131 
132 		template<typename OtherElement>
133 		void operator+= (const BasicVector4<OtherElement>& other)
134 		{
135 			m_elements[0] += static_cast<Element> (other.x());
136 			m_elements[1] += static_cast<Element> (other.y());
137 			m_elements[2] += static_cast<Element> (other.z());
138 			m_elements[3] += static_cast<Element> (other.w());
139 		}
140 
141 		/*	Define the substraction operators - and -= with any other BasicVector4 of type OtherElement
142 		 *  The vectors are substracted from each other element-wise
143 		 */
144 		template<typename OtherElement>
145 		BasicVector4<Element> operator- (const BasicVector4<OtherElement>& other) const
146 		{
147 			return BasicVector4<Element> (m_elements[0] - static_cast<Element> (other.x()), m_elements[1]
148 					- static_cast<Element> (other.y()), m_elements[2] - static_cast<Element> (other.z()), m_elements[3]
149 					- static_cast<Element> (other.w()));
150 		}
151 
152 		template<typename OtherElement>
153 		void operator-= (const BasicVector4<OtherElement>& other)
154 		{
155 			m_elements[0] -= static_cast<Element> (other.x());
156 			m_elements[1] -= static_cast<Element> (other.y());
157 			m_elements[2] -= static_cast<Element> (other.z());
158 			m_elements[3] -= static_cast<Element> (other.w());
159 		}
160 
161 		/*	Define the multiplication operators * and *= with another Vector4 of type OtherElement
162 		 *
163 		 *  The vectors are multiplied element-wise
164 		 *
165 		 *  greebo: This is mathematically kind of senseless, as this is a mixture of
166 		 *  a dot product and scalar multiplication. It can be used to scale each
167 		 *  vector component by a different factor, so maybe this comes in handy.
168 		 */
169 		template<typename OtherElement>
170 		BasicVector4<Element> operator* (const BasicVector4<OtherElement>& other) const
171 		{
172 			return BasicVector4<Element> (m_elements[0] * static_cast<Element> (other.x()), m_elements[1]
173 					* static_cast<Element> (other.y()), m_elements[2] * static_cast<Element> (other.z()), m_elements[3]
174 					* static_cast<Element> (other.w()));
175 		}
176 
177 		template<typename OtherElement>
178 		void operator*= (const BasicVector4<OtherElement>& other)
179 		{
180 			m_elements[0] *= static_cast<Element> (other.x());
181 			m_elements[1] *= static_cast<Element> (other.y());
182 			m_elements[2] *= static_cast<Element> (other.z());
183 			m_elements[3] *= static_cast<Element> (other.w());
184 		}
185 
186 		/*	Define the multiplications * and *= with a scalar
187 		 */
188 		template<typename OtherElement>
189 		BasicVector4<Element> operator* (const OtherElement& other) const
190 		{
191 			Element factor = static_cast<Element> (other);
192 			return BasicVector4<Element> (m_elements[0] * factor, m_elements[1] * factor, m_elements[2] * factor,
193 					m_elements[3] * factor);
194 		}
195 
196 		template<typename OtherElement>
197 		void operator*= (const OtherElement& other)
198 		{
199 			Element factor = static_cast<Element> (other);
200 			m_elements[0] *= factor;
201 			m_elements[1] *= factor;
202 			m_elements[2] *= factor;
203 			m_elements[3] *= factor;
204 		}
205 
206 		/*	Define the division operators / and /= with another Vector4 of type OtherElement
207 		 *  The vectors are divided element-wise
208 		 */
209 		template<typename OtherElement>
210 		BasicVector4<Element> operator/ (const BasicVector4<OtherElement>& other) const
211 		{
212 			return BasicVector4<Element> (m_elements[0] / static_cast<Element> (other.x()), m_elements[1]
213 					/ static_cast<Element> (other.y()), m_elements[2] / static_cast<Element> (other.z()), m_elements[3]
214 					/ static_cast<Element> (other.w()));
215 		}
216 
217 		template<typename OtherElement>
218 		void operator/= (const BasicVector4<OtherElement>& other)
219 		{
220 			m_elements[0] /= static_cast<Element> (other.x());
221 			m_elements[1] /= static_cast<Element> (other.y());
222 			m_elements[2] /= static_cast<Element> (other.z());
223 			m_elements[3] /= static_cast<Element> (other.w());
224 		}
225 
226 		/*	Define the scalar divisions / and /=
227 		 */
228 		template<typename OtherElement>
229 		BasicVector4<Element> operator/ (const OtherElement& other) const
230 		{
231 			Element divisor = static_cast<Element> (other);
232 			return BasicVector4<Element> (m_elements[0] / divisor, m_elements[1] / divisor, m_elements[2] / divisor,
233 					m_elements[3] / divisor);
234 		}
235 
236 		template<typename OtherElement>
237 		void operator/= (const OtherElement& other)
238 		{
239 			Element divisor = static_cast<Element> (other);
240 			m_elements[0] /= divisor;
241 			m_elements[1] /= divisor;
242 			m_elements[2] /= divisor;
243 			m_elements[3] /= divisor;
244 		}
245 
246 		/* Scalar product this vector with another Vector4,
247 		 * returning the projection of <self> onto <other>
248 		 *
249 		 * @param other
250 		 * The Vector4 to dot-product with this Vector4.
251 		 *
252 		 * @returns
253 		 * The inner product (a scalar): a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]
254 		 */
255 
256 		template<typename OtherT>
dot(const BasicVector4<OtherT> & other)257 		Element dot (const BasicVector4<OtherT>& other) const
258 		{
259 			return Element(m_elements[0] * other.x() + m_elements[1] * other.y() + m_elements[2] * other.z()
260 					+ m_elements[3] * other.w());
261 		}
262 
263 		/** Project this homogeneous Vector4 into a Cartesian Vector3
264 		 * by dividing by w.
265 		 *
266 		 * @returns
267 		 * A Vector3 representing the Cartesian equivalent of this
268 		 * homogeneous vector.
269 		 */
getProjected()270 		BasicVector3<Element> getProjected ()
271 		{
272 			return BasicVector3<Element> (m_elements[0] / m_elements[3], m_elements[1] / m_elements[3], m_elements[2]
273 					/ m_elements[3]);
274 		}
275 
276 		/**
277 		 * @return String representation of the vector - values are separated by space
278 		 */
toString()279 		std::string toString () const
280 		{
281 			std::stringstream ss;
282 			ss << m_elements[0] << " " << m_elements[1] << " " << m_elements[2] << " " << m_elements[3];
283 			return ss.str();
284 		}
285 
286 		/** Cast to std::string
287 		 */
string()288 		operator std::string() const {
289 			return toString();
290 		}
291 
292 		/** Implicit cast to C-style array. This allows a Vector4 to be
293 		 * passed directly to GL functions that expect an array (e.g.
294 		 * glFloat4fv()). These functions implicitly provide operator[]
295 		 * as well, since the C-style array provides this function.
296 		 */
297 
298 		operator const Element* () const
299 		{
300 			return m_elements;
301 		}
302 
303 		operator Element* ()
304 		{
305 			return m_elements;
306 		}
307 
308 		/*	Cast this Vector4 onto a Vector3, both const and non-const
309 		 */
getVector3()310 		BasicVector3<Element>& getVector3 ()
311 		{
312 			return *reinterpret_cast<BasicVector3<Element>*> (m_elements);
313 		}
314 
getVector3()315 		const BasicVector3<Element>& getVector3 () const
316 		{
317 			return *reinterpret_cast<const BasicVector3<Element>*> (m_elements);
318 		}
319 
320 }; // BasicVector4
321 
322 // ==========================================================================================
323 
324 // A 4-element vector stored in single-precision floating-point.
325 typedef BasicVector4<float> Vector4;
326 
327 // =============== Common Vector4 Methods ==================================================
328 
329 template<typename Element, typename OtherElement>
vector4_equal_epsilon(const BasicVector4<Element> & self,const BasicVector4<OtherElement> & other,Element epsilon)330 inline bool vector4_equal_epsilon (const BasicVector4<Element>& self, const BasicVector4<OtherElement>& other,
331 		Element epsilon)
332 {
333 	return float_equal_epsilon(self.x(), other.x(), epsilon) && float_equal_epsilon(self.y(), other.y(), epsilon)
334 			&& float_equal_epsilon(self.z(), other.z(), epsilon) && float_equal_epsilon(self.w(), other.w(), epsilon);
335 }
336