src/thirdparty/particles/pVec.h

Go to the documentation of this file.
00001 // pVec.h - yet another 3D vector class.
00002 //
00003 // Copyright 1997-2006 by David K. McAllister
00004 // Based on code Copyright 1997 by Jonathan P. Leech
00005 //
00006 // A simple 3D float vector class for internal use by the particle systems.
00007 //
00008 // The new implementation of this class uses four floats. This allows the class to be implemented using SSE intrinsics for faster execution on P4 and AMD processors.
00009 
00010 #ifndef PVEC_H_INCLUDED
00011 #define PVEC_H_INCLUDED
00012 
00013 #include <iostream>
00014 #include <cstdlib>
00015 
00016 #include <math.h>
00017 
00018 #ifndef M_PI
00019 #define M_PI 3.1415926535897932384626433f
00020 #endif
00021 
00022 #ifdef unix
00023 #define pRandf() drand48()
00024 #define pSRandf(x) srand48(x)
00025 #else
00026 #include <stdlib.h>
00027 #define P_ONEOVER_RAND_MAX (1.0f/((float) RAND_MAX))
00028 #define pRandf() (((float) rand())*P_ONEOVER_RAND_MAX)
00029 #define pSRandf(x) srand(x)
00030 #endif
00031 
00032 #define P_SQRT2PI 2.506628274631000502415765284811045253006f
00033 #define P_ONEOVERSQRT2PI (1.f / P_SQRT2PI)
00034 
00035 #ifdef _MSC_VER
00036 // This is because their stupid compiler thinks it's smart.
00037 #define inline __forceinline
00038 #endif
00039 
00040 static inline float fsqr(float f) { return f * f; }
00041 
00042 static inline bool pSameSign(const float &a, const float &b) { return a * b >= 0.0f; }
00043 static inline bool pSameSignd(const float &a, const float &b)
00044 {
00045     const int *fi = reinterpret_cast<const int *>(&a);
00046     const int *gi = reinterpret_cast<const int *>(&b);
00047     return !(((*fi) ^ (*gi)) & 0x80000000);
00048 }
00049 
00050 // Return a random number with a normal distribution.
00051 static inline float pNRandf(float sigma = 1.0f)
00052 {
00053 #define P_ONE_OVER_SIGMA_EXP (1.0f / 0.7975f)
00054 
00055     if(sigma == 0) return 0;
00056 
00057     float y;
00058     do {
00059         y = -logf(pRandf());
00060     }
00061     while(pRandf() > expf(-fsqr(y - 1.0f)*0.5f));
00062 
00063     if(rand() & 0x1)
00064         return y * sigma * P_ONE_OVER_SIGMA_EXP;
00065     else
00066         return -y * sigma * P_ONE_OVER_SIGMA_EXP;
00067 }
00068 
00069 // #pragma pack(push,16) /* Must ensure class & union 16-B aligned */
00070 
00071 class pVec
00072 {
00073     float vx, vy, vz;
00074 public:
00075 
00076     inline pVec(float ax, float ay, float az) : vx(ax), vy(ay), vz(az) {}
00077 
00078     inline pVec(float a) : vx(a), vy(a), vz(a) {}
00079 
00080     inline pVec() {}
00081 
00082     const float& x() const { return vx; }
00083     const float& y() const { return vy; }
00084     const float& z() const { return vz; }
00085 
00086     float& x() { return vx; }
00087     float& y() { return vy; }
00088     float& z() { return vz; }
00089 
00090     inline float length() const
00091     {
00092         return sqrtf(vx*vx+vy*vy+vz*vz);
00093     }
00094 
00095     inline float length2() const
00096     {
00097         return (vx*vx+vy*vy+vz*vz);
00098     }
00099 
00100     inline float normalize()
00101     {
00102         float onel = 1.0f / sqrtf(vx*vx+vy*vy+vz*vz);
00103         vx *= onel;
00104         vy *= onel;
00105         vz *= onel;
00106 
00107         return onel;
00108     }
00109 
00110     // Dot product
00111     inline float operator*(const pVec &a) const
00112     {
00113         return vx*a.x() + vy*a.y() + vz*a.z();
00114     }
00115 
00116     // Scalar multiply
00117     inline pVec operator*(const float s) const
00118     {
00119         return pVec(vx*s, vy*s, vz*s);
00120     }
00121 
00122     inline pVec operator/(const float s) const
00123     {
00124         float invs = 1.0f / s;
00125         return pVec(vx*invs, vy*invs, vz*invs);
00126     }
00127 
00128     inline pVec operator+(const pVec& a) const
00129     {
00130         return pVec(vx+a.x(), vy+a.y(), vz+a.z());
00131     }
00132 
00133     inline pVec operator-(const pVec& a) const
00134     {
00135         return pVec(vx-a.x(), vy-a.y(), vz-a.z());
00136     }
00137 
00138     inline bool operator==(const pVec &a) const
00139     {
00140         return vx==a.x() && vy==a.y() && vz==a.z();
00141     }
00142 
00143     inline pVec operator-()
00144     {
00145         vx = -vx;
00146         vy = -vy;
00147         vz = -vz;
00148         return *this;
00149     }
00150 
00151     inline pVec& operator+=(const pVec& a)
00152     {
00153         vx += a.x();
00154         vy += a.y();
00155         vz += a.z();
00156         return *this;
00157     }
00158 
00159     inline pVec& operator-=(const pVec& a)
00160     {
00161         vx -= a.x();
00162         vy -= a.y();
00163         vz -= a.z();
00164         return *this;
00165     }
00166 
00167     inline pVec& operator*=(const float a)
00168     {
00169         vx *= a;
00170         vy *= a;
00171         vz *= a;
00172         return *this;
00173     }
00174 
00175     inline pVec& operator/=(const float a)
00176     {
00177         float b = 1.0f / a;
00178         vx *= b;
00179         vy *= b;
00180         vz *= b;
00181         return *this;
00182     }
00183 
00184     inline pVec& operator=(const pVec& a)
00185     {
00186         vx = a.x();
00187         vy = a.y();
00188         vz = a.z();
00189         return *this;
00190     }
00191 
00192     // Component-wise absolute value
00193     friend inline pVec Abs(const pVec &a)
00194     {
00195         return pVec(fabs(a.x()), fabs(a.y()), fabs(a.z()));
00196     }
00197 
00198     // Component-wise multiply
00199     friend inline pVec CompMult(const pVec &a, const pVec& b)
00200     {
00201         return pVec(b.x()*a.x(), b.y()*a.y(), b.z()*a.z());
00202     }
00203 
00204     friend inline pVec Cross(const pVec& a, const pVec& b)
00205     {
00206         return pVec(
00207                    a.y()*b.z()-a.z()*b.y(),
00208                    a.z()*b.x()-a.x()*b.z(),
00209                    a.x()*b.y()-a.y()*b.x());
00210     }
00211 
00212     friend inline std::ostream& operator<<(std::ostream& os, const pVec& v)
00213     {
00214         os << &v << '[' << v.x() << ", " << v.y() << ", " << v.z() << ']';
00215 
00216         return os;
00217     }
00218 };
00219 
00220 // To offset [0 .. 1] vectors to [-.5 .. .5]
00221 static pVec vHalf(0.5, 0.5, 0.5);
00222 
00223 static inline pVec pRandVec()
00224 {
00225     return pVec(pRandf(), pRandf(), pRandf());
00226 }
00227 
00228 static inline pVec pNRandVec(float stdev)
00229 {
00230     return pVec(pNRandf(stdev), pNRandf(stdev), pNRandf(stdev));
00231 }
00232 
00233 // #pragma pack(pop) /* 16-B aligned */
00234 #endif // PVEC_H_INCLUDED

Generated on Sat Mar 15 22:55:58 2008 for Armagetron Advanced by  doxygen 1.5.4