Sirikata
|
00001 /* Sirikata Utilities -- Math Library 00002 * Vector3.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 #ifndef _SIRIKATA_VECTOR3_HPP_ 00033 #define _SIRIKATA_VECTOR3_HPP_ 00034 00035 #include <string> 00036 #include <cassert> 00037 #include <sstream> 00038 00039 #include <boost/functional/hash.hpp> 00040 00041 namespace Sirikata { 00042 template <typename scalar> class Vector3 { 00043 public: 00044 static const unsigned char size = 3; 00045 typedef scalar real; 00046 union { 00047 struct { 00048 scalar x; 00049 scalar y; 00050 scalar z; 00051 }; 00052 scalar v[3]; 00053 }; 00054 Vector3(scalar x, scalar y, scalar z) { 00055 this->x=x; 00056 this->y=y; 00057 this->z=z; 00058 } 00059 template <class V> explicit Vector3(const V&other) { 00060 x=other[0]; 00061 y=other[1]; 00062 z=other[2]; 00063 } 00064 Vector3(){} 00065 template <class V> static Vector3 fromSSE(const V&other){ 00066 return Vector3(other.x(),other.y(),other.z()); 00067 } 00068 scalar&operator[](const unsigned int i) { 00069 assert(i<3); 00070 return v[i]; 00071 } 00072 #if 0 00073 template<class T> operator T() const{ 00074 return T(x,y,z); 00075 } 00076 #else 00077 template<class T> T convert() const{ 00078 return T(x,y,z); 00079 } 00080 #endif 00081 template<class T> Vector3<T> downCast() const{ 00082 return Vector3<T>((T)x,(T)y,(T)z); 00083 } 00084 00085 scalar operator[](const unsigned int i) const{ 00086 assert(i<3); 00087 return v[i]; 00088 } 00089 Vector3&operator=(scalar other) { 00090 x=other; 00091 y=other; 00092 z=other; 00093 return *this; 00094 } 00095 static Vector3 zero() { 00096 return Vector3(0,0,0); 00097 } 00098 static Vector3 unitX() { 00099 return Vector3(1,0,0); 00100 } 00101 static Vector3 unitY() { 00102 return Vector3(0,1,0); 00103 } 00104 static Vector3 unitZ() { 00105 return Vector3(0,0,1); 00106 } 00107 static Vector3 unitNegX() { 00108 return Vector3(-1,0,0); 00109 } 00110 static Vector3 unitNegY() { 00111 return Vector3(0,-1,0); 00112 } 00113 static Vector3 unitNegZ() { 00114 return Vector3(0,0,-1); 00115 } 00116 Vector3 operator*(scalar scale) const { 00117 return Vector3(x*scale,y*scale,z*scale); 00118 } 00119 Vector3 scale(scalar scale) const { return (*this)*scale; } 00120 Vector3 operator/(scalar scale) const { 00121 return Vector3(x/scale,y/scale,z/scale); 00122 } 00123 Vector3 operator+(const Vector3&other) const { 00124 return Vector3(x+other.x,y+other.y,z+other.z); 00125 } 00126 Vector3 componentMultiply(const Vector3&other) const { 00127 return Vector3(x*other.x,y*other.y,z*other.z); 00128 } 00129 Vector3 operator-(const Vector3&other) const { 00130 return Vector3(x-other.x,y-other.y,z-other.z); 00131 } 00132 Vector3 operator-() const { 00133 return Vector3(-x,-y,-z); 00134 } 00135 Vector3& operator*=(scalar scale) { 00136 x*=scale; 00137 y*=scale; 00138 z*=scale; 00139 return *this; 00140 } 00141 Vector3& operator/=(scalar scale) { 00142 x/=scale; 00143 y/=scale; 00144 z/=scale; 00145 return *this; 00146 } 00147 Vector3& operator+=(const Vector3& other) { 00148 x+=other.x; 00149 y+=other.y; 00150 z+=other.z; 00151 return *this; 00152 } 00153 Vector3& operator-=(const Vector3& other) { 00154 x-=other.x; 00155 y-=other.y; 00156 z-=other.z; 00157 return *this; 00158 } 00159 Vector3 cross(const Vector3&other) const { 00160 return Vector3(y*other.z-z*other.y, 00161 z*other.x-x*other.z, 00162 x*other.y-y*other.x); 00163 } 00164 scalar dot(const Vector3 &other) const{ 00165 return x*other.x+y*other.y+z*other.z; 00166 } 00167 Vector3 min(const Vector3&other)const { 00168 return Vector3(other.x<x?other.x:x, 00169 other.y<y?other.y:y, 00170 other.z<z?other.z:z); 00171 } 00172 Vector3 max(const Vector3&other)const { 00173 return Vector3(other.x>x?other.x:x, 00174 other.y>y?other.y:y, 00175 other.z>z?other.z:z); 00176 } 00177 scalar lengthSquared()const { 00178 return dot(*this); 00179 } 00180 scalar length()const { 00181 return (scalar)sqrt(dot(*this)); 00182 } 00183 bool operator==(const Vector3&other)const { 00184 return x==other.x&&y==other.y&&z==other.z; 00185 } 00186 bool operator!=(const Vector3&other)const { 00187 return x!=other.x||y!=other.y||z!=other.z; 00188 } 00189 Vector3 normal()const { 00190 scalar len=length(); 00191 if (len>1e-08) 00192 return *this/len; 00193 return *this; 00194 } 00195 scalar normalizeThis() { 00196 scalar len=length(); 00197 if (len>1e-08) 00198 *this/=len; 00199 return len; 00200 } 00201 std::string toString()const { 00202 std::ostringstream os; 00203 os<<'<'<<x<<","<<y<<","<<z<<'>'; 00204 return os.str(); 00205 } 00206 Vector3 reflect(const Vector3& normal)const { 00207 return Vector3(*this-normal*((scalar)2.0*this->dot(normal))); 00208 } 00209 00210 size_t hash() const { 00211 size_t seed = 0; 00212 boost::hash_combine(seed, x); 00213 boost::hash_combine(seed, y); 00214 boost::hash_combine(seed, z); 00215 return seed; 00216 } 00217 00218 class Hasher{public: 00219 size_t operator() (const Vector3 &v) const { 00220 return v.hash(); 00221 } 00222 }; 00223 }; 00224 00225 template<typename scalar> inline Vector3<scalar> operator *(scalar lhs, const Vector3<scalar> &rhs) { 00226 return Vector3<scalar>(lhs*rhs.x,lhs*rhs.y,lhs*rhs.z); 00227 } 00228 template<typename scalar> inline Vector3<scalar> operator /(scalar lhs, const Vector3<scalar> &rhs) { 00229 return Vector3<scalar>(lhs/rhs.x,lhs/rhs.y,lhs/rhs.z); 00230 } 00231 template<typename scalar> inline std::ostream& operator <<(std::ostream& os, const Vector3<scalar> &rhs) { 00232 os<<'<'<<rhs.x<<","<<rhs.y<<","<<rhs.z<<'>'; 00233 return os; 00234 } 00235 template<typename scalar> inline std::istream& operator >>(std::istream& is, Vector3<scalar> &rhs) { 00236 // FIXME this should be more robust. It currently relies on the exact format provided by operator << 00237 char dummy; 00238 is >> dummy >> rhs.x >> dummy >> rhs.y >> dummy >> rhs.z >> dummy; 00239 return is; 00240 } 00241 00242 } 00243 #endif