Vector4.h

Go to the documentation of this file.
00001 #ifndef VECTOR4_H_
00002 #define VECTOR4_H_
00003 
00004 /* greebo: This file contains the templated class definition of the three-component vector
00005  *
00006  * BasicVector4: A vector with three components of type <Element>
00007  *
00008  * The BasicVector4 is equipped with the most important operators like *, *= and so on.
00009  *
00010  * Note: The most commonly used Vector4 is a BasicVector4<float>, this is also defined in this file
00011  *
00012  * Note: that the multiplication of a Vector4 with another one (Vector4*Vector4) does NOT
00013  * result in an inner product but in a component-wise scaling. Use the .dot() method to
00014  * execute an inner product of two vectors.
00015  */
00016 
00017 #include "FloatTools.h"
00018 #include "Vector3.h"
00019 
00020 // A 4-element vector of type <Element>
00021 template<typename Element>
00022 class BasicVector4
00023 {
00024 
00025         // The components of this vector
00026         Element m_elements[4];
00027 
00028     public:
00029 
00030         // Constructor (no arguments)
00031         BasicVector4 ()
00032         {
00033         }
00034 
00035         // Construct a BasicVector4 out of the 4 arguments
00036         BasicVector4 (Element x_, Element y_, Element z_, Element w_)
00037         {
00038             x() = x_;
00039             y() = y_;
00040             z() = z_;
00041             w() = w_;
00042         }
00043 
00044         // Construct a BasicVector4 out of a Vector3 plus a fourth argument
00045         BasicVector4 (const BasicVector3<Element>& self, Element w_)
00046         {
00047             x() = self.x();
00048             y() = self.y();
00049             z() = self.z();
00050             w() = w_;
00051         }
00052 
00053         // Return non-constant references to the components
00054         Element& x ()
00055         {
00056             return m_elements[0];
00057         }
00058         Element& y ()
00059         {
00060             return m_elements[1];
00061         }
00062         Element& z ()
00063         {
00064             return m_elements[2];
00065         }
00066         Element& w ()
00067         {
00068             return m_elements[3];
00069         }
00070 
00071         // Return constant references to the components
00072         const Element& x () const
00073         {
00074             return m_elements[0];
00075         }
00076         const Element& y () const
00077         {
00078             return m_elements[1];
00079         }
00080         const Element& z () const
00081         {
00082             return m_elements[2];
00083         }
00084         const Element& w () const
00085         {
00086             return m_elements[3];
00087         }
00088 
00089         Element index (std::size_t i) const
00090         {
00091             return m_elements[i];
00092         }
00093         Element& index (std::size_t i)
00094         {
00095             return m_elements[i];
00096         }
00097 
00100         bool operator== (const BasicVector4& other) const
00101         {
00102             return (other.x() == x() && other.y() == y() && other.z() == z() && other.w() == w());
00103         }
00104 
00107         bool operator!= (const BasicVector4& other) const
00108         {
00109             return !(*this == other);
00110         }
00111 
00112         /*  Define the addition operators + and += with any other BasicVector4 of type OtherElement
00113          *  The vectors are added to each other element-wise
00114          */
00115         template<typename OtherElement>
00116         BasicVector4<Element> operator+ (const BasicVector4<OtherElement>& other) const
00117         {
00118             return BasicVector4<Element> (m_elements[0] + static_cast<Element> (other.x()), m_elements[1]
00119                     + static_cast<Element> (other.y()), m_elements[2] + static_cast<Element> (other.z()), m_elements[3]
00120                     + static_cast<Element> (other.w()));
00121         }
00122 
00123         template<typename OtherElement>
00124         void operator+= (const BasicVector4<OtherElement>& other)
00125         {
00126             m_elements[0] += static_cast<Element> (other.x());
00127             m_elements[1] += static_cast<Element> (other.y());
00128             m_elements[2] += static_cast<Element> (other.z());
00129             m_elements[3] += static_cast<Element> (other.w());
00130         }
00131 
00132         /*  Define the substraction operators - and -= with any other BasicVector4 of type OtherElement
00133          *  The vectors are substracted from each other element-wise
00134          */
00135         template<typename OtherElement>
00136         BasicVector4<Element> operator- (const BasicVector4<OtherElement>& other) const
00137         {
00138             return BasicVector4<Element> (m_elements[0] - static_cast<Element> (other.x()), m_elements[1]
00139                     - static_cast<Element> (other.y()), m_elements[2] - static_cast<Element> (other.z()), m_elements[3]
00140                     - static_cast<Element> (other.w()));
00141         }
00142 
00143         template<typename OtherElement>
00144         void operator-= (const BasicVector4<OtherElement>& other)
00145         {
00146             m_elements[0] -= static_cast<Element> (other.x());
00147             m_elements[1] -= static_cast<Element> (other.y());
00148             m_elements[2] -= static_cast<Element> (other.z());
00149             m_elements[3] -= static_cast<Element> (other.w());
00150         }
00151 
00152         /*  Define the multiplication operators * and *= with another Vector4 of type OtherElement
00153          *
00154          *  The vectors are multiplied element-wise
00155          *
00156          *  greebo: This is mathematically kind of senseless, as this is a mixture of
00157          *  a dot product and scalar multiplication. It can be used to scale each
00158          *  vector component by a different factor, so maybe this comes in handy.
00159          */
00160         template<typename OtherElement>
00161         BasicVector4<Element> operator* (const BasicVector4<OtherElement>& other) const
00162         {
00163             return BasicVector4<Element> (m_elements[0] * static_cast<Element> (other.x()), m_elements[1]
00164                     * static_cast<Element> (other.y()), m_elements[2] * static_cast<Element> (other.z()), m_elements[3]
00165                     * static_cast<Element> (other.w()));
00166         }
00167 
00168         template<typename OtherElement>
00169         void operator*= (const BasicVector4<OtherElement>& other)
00170         {
00171             m_elements[0] *= static_cast<Element> (other.x());
00172             m_elements[1] *= static_cast<Element> (other.y());
00173             m_elements[2] *= static_cast<Element> (other.z());
00174             m_elements[3] *= static_cast<Element> (other.w());
00175         }
00176 
00177         /*  Define the multiplications * and *= with a scalar
00178          */
00179         template<typename OtherElement>
00180         BasicVector4<Element> operator* (const OtherElement& other) const
00181         {
00182             Element factor = static_cast<Element> (other);
00183             return BasicVector4<Element> (m_elements[0] * factor, m_elements[1] * factor, m_elements[2] * factor,
00184                     m_elements[3] * factor);
00185         }
00186 
00187         template<typename OtherElement>
00188         void operator*= (const OtherElement& other)
00189         {
00190             Element factor = static_cast<Element> (other);
00191             m_elements[0] *= factor;
00192             m_elements[1] *= factor;
00193             m_elements[2] *= factor;
00194             m_elements[3] *= factor;
00195         }
00196 
00197         /*  Define the division operators / and /= with another Vector4 of type OtherElement
00198          *  The vectors are divided element-wise
00199          */
00200         template<typename OtherElement>
00201         BasicVector4<Element> operator/ (const BasicVector4<OtherElement>& other) const
00202         {
00203             return BasicVector4<Element> (m_elements[0] / static_cast<Element> (other.x()), m_elements[1]
00204                     / static_cast<Element> (other.y()), m_elements[2] / static_cast<Element> (other.z()), m_elements[3]
00205                     / static_cast<Element> (other.w()));
00206         }
00207 
00208         template<typename OtherElement>
00209         void operator/= (const BasicVector4<OtherElement>& other)
00210         {
00211             m_elements[0] /= static_cast<Element> (other.x());
00212             m_elements[1] /= static_cast<Element> (other.y());
00213             m_elements[2] /= static_cast<Element> (other.z());
00214             m_elements[3] /= static_cast<Element> (other.w());
00215         }
00216 
00217         /*  Define the scalar divisions / and /=
00218          */
00219         template<typename OtherElement>
00220         BasicVector4<Element> operator/ (const OtherElement& other) const
00221         {
00222             Element divisor = static_cast<Element> (other);
00223             return BasicVector4<Element> (m_elements[0] / divisor, m_elements[1] / divisor, m_elements[2] / divisor,
00224                     m_elements[3] / divisor);
00225         }
00226 
00227         template<typename OtherElement>
00228         void operator/= (const OtherElement& other)
00229         {
00230             Element divisor = static_cast<Element> (other);
00231             m_elements[0] /= divisor;
00232             m_elements[1] /= divisor;
00233             m_elements[2] /= divisor;
00234             m_elements[3] /= divisor;
00235         }
00236 
00237         /* Scalar product this vector with another Vector4,
00238          * returning the projection of <self> onto <other>
00239          *
00240          * @param other
00241          * The Vector4 to dot-product with this Vector4.
00242          *
00243          * @returns
00244          * The inner product (a scalar): a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]
00245          */
00246 
00247         template<typename OtherT>
00248         Element dot (const BasicVector4<OtherT>& other) const
00249         {
00250             return Element(m_elements[0] * other.x() + m_elements[1] * other.y() + m_elements[2] * other.z()
00251                     + m_elements[3] * other.w());
00252         }
00253 
00261         BasicVector3<Element> getProjected ()
00262         {
00263             return BasicVector3<Element> (m_elements[0] / m_elements[3], m_elements[1] / m_elements[3], m_elements[2]
00264                     / m_elements[3]);
00265         }
00266 
00270         std::string toString () const
00271         {
00272             std::stringstream ss;
00273             ss << m_elements[0] << " " << m_elements[1] << " " << m_elements[2] << " " << m_elements[3];
00274             return ss.str();
00275         }
00276 
00283         operator const Element* () const
00284         {
00285             return m_elements;
00286         }
00287 
00288         operator Element* ()
00289         {
00290             return m_elements;
00291         }
00292 
00293         /*  Cast this Vector4 onto a Vector3, both const and non-const
00294          */
00295         BasicVector3<Element>& getVector3 ()
00296         {
00297             return *reinterpret_cast<BasicVector3<Element>*> (m_elements);
00298         }
00299 
00300         const BasicVector3<Element>& getVector3 () const
00301         {
00302             return *reinterpret_cast<const BasicVector3<Element>*> (m_elements);
00303         }
00304 
00305 }; // BasicVector4
00306 
00307 // ==========================================================================================
00308 
00309 // A 4-element vector stored in single-precision floating-point.
00310 typedef BasicVector4<float> Vector4;
00311 
00312 // =============== Common Vector4 Methods ==================================================
00313 
00314 template<typename Element, typename OtherElement>
00315 inline bool vector4_equal_epsilon (const BasicVector4<Element>& self, const BasicVector4<OtherElement>& other,
00316         Element epsilon)
00317 {
00318     return float_equal_epsilon(self.x(), other.x(), epsilon) && float_equal_epsilon(self.y(), other.y(), epsilon)
00319             && float_equal_epsilon(self.z(), other.z(), epsilon) && float_equal_epsilon(self.w(), other.w(), epsilon);
00320 }
00321 
00322 #endif /*VECTOR4_H_*/

Generated by  doxygen 1.6.2