Sirikata
libcore/include/sirikata/core/util/Vector4.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Math Library
00002  *  Vector4.hpp
00003  *
00004  *  Copyright (c) 2009, Daniel Reiter Horn
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef _SIRIKATA_VECTOR4_HPP_
00034 #define _SIRIKATA_VECTOR4_HPP_
00035 
00036 #include <string>
00037 #include <cassert>
00038 #include <sstream>
00039 
00040 namespace Sirikata {
00041 template <typename scalar> class Vector3;
00042 
00043 template <typename scalar> class Vector4 {
00044 public:
00045     static const unsigned char size = 4;
00046     typedef scalar real;
00047     union {
00048         struct {
00049             scalar x;
00050             scalar y;
00051             scalar z;
00052             scalar w;
00053         };
00054         scalar v[4];
00055     };
00056     Vector4(scalar x, scalar y, scalar z, scalar w) {
00057         this->x=x;
00058         this->y=y;
00059         this->z=z;
00060         this->w=w;
00061     }
00062     Vector4(){}
00063 
00064     Vector4(const Vector3<scalar>& xyz, scalar w) {
00065         this->x = xyz.x;
00066         this->y = xyz.y;
00067         this->z = xyz.z;
00068         this->w = w;
00069     }
00070 
00071     template<class T>T convert(const T*ptr=NULL) const{
00072         return T(x,y,z,w);
00073     }
00074     template<class T> Vector4<T> downCast() const{
00075         return Vector4<T>((T)x,(T)y,(T)z,(T)w);
00076     }
00077 
00078     template <class V> static Vector4 fromArray(const V&other){
00079         return Vector4(other[0],other[1],other[2],other[3]);
00080     }
00081 
00082     template <class V> static Vector4 fromSSE(const V&other){
00083         return Vector4(other.x(),other.y(),other.z(),other.w());
00084     }
00085     scalar&operator[](const unsigned int i) {
00086         assert(i<4);
00087         return v[i];
00088     }
00089     scalar operator[](const unsigned int i) const{
00090         assert(i<4);
00091         return v[i];
00092     }
00093     Vector4&operator=(scalar other) {
00094         x=other;
00095         y=other;
00096         z=other;
00097         w=other;
00098         return *this;
00099     }
00100     static Vector4 zero() {
00101         return Vector4(0,0,0,0);
00102     }
00103     static Vector4 unitX() {
00104         return Vector4(1,0,0,0);
00105     }
00106     static Vector4 unitY() {
00107         return Vector4(0,1,0,0);
00108     }
00109     static Vector4 unitZ() {
00110         return Vector4(0,0,1,0);
00111     }
00112     static Vector4 unitNegX() {
00113         return Vector4(-1,0,0,0);
00114     }
00115     static Vector4 unitNegY() {
00116         return Vector4(0,-1,0,0);
00117     }
00118     static Vector4 unitNegZ() {
00119         return Vector4(0,0,-1,0);
00120     }
00121     Vector4 operator*(scalar scale) const {
00122         return Vector4(x*scale,y*scale,z*scale,w*scale);
00123     }
00124     Vector4 operator/(scalar scale) const {
00125         return Vector4(x/scale,y/scale,z/scale,w/scale);
00126     }
00127     Vector4 operator+(const Vector4&other) const {
00128         return Vector4(x+other.x,y+other.y,z+other.z,w+other.w);
00129     }
00130     Vector4 operator-(const Vector4&other) const {
00131         return Vector4(x-other.x,y-other.y,z-other.z,w-other.w);
00132     }
00133     Vector4 operator-() const {
00134         return Vector4(-x,-y,-z,-w);
00135     }
00136     Vector4& operator*=(scalar scale) {
00137         x*=scale;
00138         y*=scale;
00139         z*=scale;
00140         w*=scale;
00141         return *this;
00142     }
00143     Vector4& operator/=(scalar scale) {
00144         x/=scale;
00145         y/=scale;
00146         z/=scale;
00147         w/=scale;
00148         return *this;
00149     }
00150     Vector4& operator+=(const Vector4& other) {
00151         x+=other.x;
00152         y+=other.y;
00153         z+=other.z;
00154         w+=other.w;
00155         return *this;
00156     }
00157     Vector4& operator-=(const Vector4& other) {
00158         x-=other.x;
00159         y-=other.y;
00160         z-=other.z;
00161         w-=other.w;
00162         return *this;
00163     }
00164     Vector4 componentMultiply(const Vector4&other) const {
00165         return Vector4(x*other.x,y*other.y,z*other.z,w*other.w);
00166     }
00167     scalar dot(const Vector4 &other) const{
00168         return x*other.x+y*other.y+z*other.z+w*other.w;
00169     }
00170     Vector4 min(const Vector4&other)const {
00171         return Vector4(other.x<x?other.x:x,
00172                        other.y<y?other.y:y,
00173                        other.z<z?other.z:z,
00174                        other.w<w?other.w:w);
00175     }
00176     Vector4 max(const Vector4&other)const {
00177         return Vector4(other.x>x?other.x:x,
00178                        other.y>y?other.y:y,
00179                        other.z>z?other.z:z,
00180                        other.w>w?other.w:w);
00181     }
00182     scalar lengthSquared()const {
00183         return dot(*this);
00184     }
00185     scalar length()const {
00186         return (scalar)sqrt(dot(*this));
00187     }
00188     bool operator==(const Vector4&other)const {
00189         return x==other.x&&y==other.y&&z==other.z&&w==other.w;
00190     }
00191     bool operator!=(const Vector4&other)const {
00192         return x!=other.x||y!=other.y||z!=other.z||w!=other.w;
00193     }
00194     Vector4 normal()const {
00195         scalar len=length();
00196         if (len>1e-08)
00197             return *this/len;
00198         return *this;
00199     }
00200     scalar normalizeThis() {
00201         scalar len=length();
00202         if (len>1e-08)
00203             *this/=len;
00204         return len;
00205     }
00206     std::string toString()const {
00207         std::ostringstream os;
00208         os<<'<'<<x<<","<<y<<","<<z<<","<<w<<'>';
00209         return os.str();
00210     }
00211 };
00212 
00213 template<typename scalar> inline Vector4<scalar> operator *(scalar lhs, const Vector4<scalar> &rhs) {
00214     return Vector4<scalar>(lhs*rhs.x,lhs*rhs.y,lhs*rhs.z,lhs*rhs.w);
00215 }
00216 template<typename scalar> inline Vector4<scalar> operator /(scalar lhs, const Vector4<scalar> &rhs) {
00217     return Vector4<scalar>(lhs/rhs.x,lhs/rhs.y,lhs/rhs.z,lhs/rhs.w);
00218 }
00219 template<typename scalar> inline std::ostream& operator <<(std::ostream& os, const Vector4<scalar> &rhs) {
00220     os<<'<'<<rhs.x<<","<<rhs.y<<","<<rhs.z<<","<<rhs.w<<'>';
00221     return os;
00222 }
00223 template<typename scalar> inline std::istream& operator >>(std::istream& is, Vector4<scalar> &rhs) {
00224     // FIXME this should be more robust.  It currently relies on the exact format provided by operator <<
00225     char dummy;
00226     is >> dummy >> rhs.x >> dummy >> rhs.y >> dummy >> rhs.z >> dummy >> rhs.w >> dummy;
00227     return is;
00228 }
00229 
00230 }
00231 
00232 #endif //_SIRIKATA_VECTOR4_HPP_