00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __SP_DIMENSION_VECTOR3D_H__
00009 #define __SP_DIMENSION_VECTOR3D_H__
00010
00011
00012 #include "Base/spStandard.hpp"
00013 #include "Base/spMathCore.hpp"
00014
00015
00016 namespace sp
00017 {
00018 namespace dim
00019 {
00020
00021
00022 template <typename T> class vector4d;
00023 template <typename T> class point2d;
00024 template <typename T> class size2d;
00025
00026
00028 enum EAxisTypes
00029 {
00030 AXIS_X_POSITIVE = 0,
00031 AXIS_X_NEGATIVE,
00032 AXIS_Y_POSITIVE,
00033 AXIS_Y_NEGATIVE,
00034 AXIS_Z_POSITIVE,
00035 AXIS_Z_NEGATIVE,
00036 };
00037
00038
00043 template <typename T> class vector3d
00044 {
00045
00046 public:
00047
00048 vector3d() :
00049 X(0),
00050 Y(0),
00051 Z(0)
00052 {
00053 }
00054 vector3d(const T &Size) :
00055 X(Size),
00056 Y(Size),
00057 Z(Size)
00058 {
00059 }
00060 vector3d(const T &VecX, const T &VecY, const T &VecZ) :
00061 X(VecX),
00062 Y(VecY),
00063 Z(VecZ)
00064 {
00065 }
00066 vector3d(const T &VecX, const T &VecY, const T &VecZ, const T &VecW) :
00067 X(VecX*VecW),
00068 Y(VecY*VecW),
00069 Z(VecZ*VecW)
00070 {
00071 }
00072 vector3d(const vector3d<T> &Other) :
00073 X(Other.X),
00074 Y(Other.Y),
00075 Z(Other.Z)
00076 {
00077 }
00078 vector3d(const vector4d<T> &Other);
00079 vector3d(const point2d<T> &Other);
00080 vector3d(const size2d<T> &Other);
00081 ~vector3d()
00082 {
00083 }
00084
00085
00086
00087 inline bool operator == (const vector3d<T> &other) const
00088 {
00089 return math::Equal(X, other.X) && math::Equal(Y, other.Y) && math::Equal(Z, other.Z);
00090 }
00091 inline bool operator != (const vector3d<T> &other) const
00092 {
00093 return !math::Equal(X, other.X) || !math::Equal(Y, other.Y) || !math::Equal(Z, other.Z);
00094 }
00095
00096 inline bool operator <= (const vector3d<T> &other) const
00097 {
00098 return
00099 ( X < other.X || math::Equal(X, other.X) ) ||
00100 ( math::Equal(X, other.X) && ( Y < other.Y || math::Equal(Y, other.Y) ) ) ||
00101 ( math::Equal(X, other.X) && math::Equal(Y, other.Y) && ( Z < other.Z || math::Equal(Z, other.Z) ) );
00102 }
00103 inline bool operator >= (const vector3d<T> &other) const
00104 {
00105 return
00106 ( X > other.X || math::Equal(X, other.X) ) ||
00107 ( math::Equal(X, other.X) && (Y > other.Y || math::Equal(Y, other.Y) ) ) ||
00108 ( math::Equal(X, other.X) && math::Equal(Y, other.Y) && ( Z > other.Z || math::Equal(Z, other.Z) ) );
00109 }
00110
00111 inline bool operator < (const vector3d<T> &other) const
00112 {
00113 return
00114 ( X < other.X && !math::Equal(X, other.X) ) ||
00115 ( math::Equal(X, other.X) && Y < other.Y && !math::Equal(Y, other.Y) ) ||
00116 ( math::Equal(X, other.X) && math::Equal(Y, other.Y) && Z < other.Z && !math::Equal(Z, other.Z) );
00117 }
00118 inline bool operator > (const vector3d<T> &other) const
00119 {
00120 return
00121 ( X > other.X && !math::Equal(X, other.X) ) ||
00122 ( math::Equal(X, other.X) && Y > other.Y && !math::Equal(Y, other.Y) ) ||
00123 ( math::Equal(X, other.X) && math::Equal(Y, other.Y) && Z > other.Z && !math::Equal(Z, other.Z) );
00124 }
00125
00126
00127
00129 inline vector3d<T>& operator ++ ()
00130 {
00131 ++X; ++Y; ++Z; return *this;
00132 }
00134 inline vector3d<T>& operator ++ (int)
00135 {
00136 const vector3d<T> Tmp(*this);
00137 ++*this;
00138 return Tmp;
00139 }
00140
00142 inline vector3d<T>& operator -- ()
00143 {
00144 --X; --Y; --Z; return *this;
00145 }
00147 inline vector3d<T>& operator -- (int)
00148 {
00149 const vector3d<T> Tmp(*this);
00150 --*this;
00151 return Tmp;
00152 }
00153
00154 inline vector3d<T> operator + (const vector3d<T> &other) const
00155 {
00156 return vector3d<T>(X + other.X, Y + other.Y, Z + other.Z);
00157 }
00158 inline vector3d<T>& operator += (const vector3d<T> &other)
00159 {
00160 X += other.X; Y += other.Y; Z += other.Z; return *this;
00161 }
00162
00163 inline vector3d<T> operator - (const vector3d<T> &other) const
00164 {
00165 return vector3d<T>(X - other.X, Y - other.Y, Z - other.Z);
00166 }
00167 inline vector3d<T>& operator -= (const vector3d<T> &other)
00168 {
00169 X -= other.X; Y -= other.Y; Z -= other.Z; return *this;
00170 }
00171
00172 inline vector3d<T> operator / (const vector3d<T> &other) const
00173 {
00174 return vector3d<T>(X / other.X, Y / other.Y, Z / other.Z);
00175 }
00176 inline vector3d<T>& operator /= (const vector3d<T> &other)
00177 {
00178 X /= other.X; Y /= other.Y; Z /= other.Z; return *this;
00179 }
00180
00181 inline vector3d<T> operator * (const vector3d<T> &other) const
00182 {
00183 return vector3d<T>(X * other.X, Y * other.Y, Z * other.Z);
00184 }
00185 inline vector3d<T>& operator *= (const vector3d<T> &other)
00186 {
00187 X *= other.X; Y *= other.Y; Z *= other.Z; return *this;
00188 }
00189
00190 inline vector3d<T> operator * (const T &Size) const
00191 {
00192 return vector3d<T>(X * Size, Y * Size, Z * Size);
00193 }
00194 inline vector3d<T>& operator *= (const T &Size)
00195 {
00196 X *= Size; Y *= Size; Z *= Size; return *this;
00197 }
00198
00199 inline vector3d<T> operator / (const T &Size) const
00200 {
00201 return *this * (T(1) / Size);
00202 }
00203 inline vector3d<T>& operator /= (const T &Size)
00204 {
00205 return *this *= (T(1) / Size);
00206 }
00207
00208 inline vector3d<T> operator - () const
00209 {
00210 return vector3d<T>(-X, -Y, -Z);
00211 }
00212
00213
00214
00215 inline const T operator [] (u32 i) const
00216 {
00217 return i < 3 ? *(&X + i) : static_cast<T>(0.0);
00218 }
00219
00220 inline T& operator [] (u32 i)
00221 {
00222 return *(&X + i);
00223 }
00224
00225
00226
00228 inline T dot(const vector3d<T> &other) const
00229 {
00230 return X*other.X + Y*other.Y + Z*other.Z;
00231 }
00232
00234 inline vector3d<T> cross(const vector3d<T> &other) const
00235 {
00236 return vector3d<T>(
00237 Y*other.Z - other.Y*Z,
00238 Z*other.X - other.Z*X,
00239 X*other.Y - other.X*Y
00240 );
00241 }
00242
00244 inline T getLength() const
00245 {
00246 return sqrt(X*X + Y*Y + Z*Z);
00247 }
00248
00250 inline T getLengthSq() const
00251 {
00252 return X*X + Y*Y + Z*Z;
00253 }
00254
00256 inline T getAngle(const vector3d<T> &other) const
00257 {
00258 return static_cast<T>(math::ACos( dot(other) / (getLength()*other.getLength()) ));
00259 }
00260
00261 inline vector3d<T>& setInvert()
00262 {
00263 X = -X; Y = -Y; Z = -Z; return *this;
00264 }
00265 inline vector3d<T> getInvert() const
00266 {
00267 return vector3d<T>(-X, -Y, -Z);
00268 }
00269
00270 inline vector3d<T>& setRound(s32 Precision)
00271 {
00272 Precision = static_cast<s32>(pow(10, Precision));
00273 X = static_cast<T>(static_cast<s32>(X*Precision)) / Precision;
00274 Y = static_cast<T>(static_cast<s32>(Y*Precision)) / Precision;
00275 Z = static_cast<T>(static_cast<s32>(Z*Precision)) / Precision;
00276 return *this;
00277 }
00278 inline vector3d<T> getRound(s32 Precision) const
00279 {
00280 Precision = static_cast<s32>(pow(10, Precision));
00281 return vector3d<T>(
00282 static_cast<T>(static_cast<s32>(X*Precision)) / Precision,
00283 static_cast<T>(static_cast<s32>(Y*Precision)) / Precision,
00284 static_cast<T>(static_cast<s32>(Z*Precision)) / Precision
00285 );
00286 }
00287
00288 inline bool equal(const vector3d<T> &other, f32 Tolerance = math::ROUNDING_ERROR) const
00289 {
00290 return
00291 (X + Tolerance > other.X) && (X - Tolerance < other.X) &&
00292 (Y + Tolerance > other.Y) && (Y - Tolerance < other.Y) &&
00293 (Z + Tolerance > other.Z) && (Z - Tolerance < other.Z);
00294 }
00295 inline bool empty() const
00296 {
00297 return equal(0);
00298 }
00299
00300 inline void make2DProjection(s32 ScreenWidth, s32 ScreenHeight)
00301 {
00302 X = X * static_cast<f32>(ScreenWidth /2) + ScreenWidth /2;
00303 Y = - Y * static_cast<f32>(ScreenHeight/2) + ScreenHeight/2;
00304 Z = T(0);
00305 }
00306 inline void make2DProjection(f32 FOV, s32 ScreenWidth, s32 ScreenHeight)
00307 {
00308 X = X / Z * FOV + ScreenWidth /2;
00309 Y = - Y / Z * FOV + ScreenHeight/2;
00310 }
00311
00312 inline vector3d<T>& setAbs()
00313 {
00314 X = X > 0 ? X : -X;
00315 Y = Y > 0 ? Y : -Y;
00316 Z = Z > 0 ? Z : -Z;
00317 return *this;
00318 }
00319 inline vector3d<T> getAbs() const
00320 {
00321 return vector3d<T>(
00322 X > 0 ? X : -X,
00323 Y > 0 ? Y : -Y,
00324 Z > 0 ? Z : -Z
00325 );
00326 }
00327
00328 inline vector3d<T>& normalize()
00329 {
00330 T n = X*X + Y*Y + Z*Z;
00331
00332 if (n == T(0) || n == T(1))
00333 return *this;
00334
00335 n = T(1) / sqrt(n);
00336
00337 X *= n;
00338 Y *= n;
00339 Z *= n;
00340
00341 return *this;
00342 }
00343 inline vector3d<T>& sign()
00344 {
00345 if (X > 0) X = 1; else if (X < 0) X = -1;
00346 if (Y > 0) Y = 1; else if (Y < 0) Y = -1;
00347 if (Z > 0) Z = 1; else if (Z < 0) Z = -1;
00348 return *this;
00349 }
00350
00351 inline vector3d<T>& setLength(const T &Length)
00352 {
00353 normalize();
00354 *this *= Length;
00355 return *this;
00356 }
00357
00358 inline T getDistanceFromSq(const vector3d<T> &other) const
00359 {
00360 return vector3d<T>(X - other.X, Y - other.Y, Z - other.Z).getLengthSq();
00361 }
00362
00363 inline bool isBetweenPoints(const vector3d<T> &Begin, const vector3d<T> &End) const
00364 {
00365 const T Temp = (End - Begin).getLengthSq();
00366 return getDistanceFromSq(Begin) <= Temp && getDistanceFromSq(End) <= Temp;
00367 }
00368
00369 inline bool isPointInsideSphere(const vector3d<T> &Center, const f32 Radius) const
00370 {
00371 return math::Pow2(X - Center.X) + math::Pow2(Y - Center.Y) + math::Pow2(Z - Center.Z) < math::Pow2(Radius);
00372 }
00373
00374 inline vector3d<T> getInterpolatedQuadratic(const vector3d<T> &v2, const vector3d<T> &v3, const T d) const
00375 {
00376 const T inv = static_cast<T>(1.0) - d;
00377 const T mul0 = inv * inv;
00378 const T mul1 = static_cast<T>(2.0) * d * inv;
00379 const T mul2 = d * d;
00380
00381 return vector3d<T>(
00382 X * mul0 + v2.X * mul1 + v3.X * mul2,
00383 Y * mul0 + v2.Y * mul1 + v3.Y * mul2,
00384 Z * mul0 + v2.Z * mul1 + v3.Z * mul2
00385 );
00386 }
00387
00388 inline vector3d<T> getRotatedAxis(const T &Angle, vector3d<T> Axis) const
00389 {
00390 if (Angle == T(0))
00391 return *this;
00392
00393 Axis.normalize();
00394
00395 vector3d<T> rotMatrixRow1, rotMatrixRow2, rotMatrixRow3;
00396
00397 T sinAngle = sin(Angle*math::DEG);
00398 T cosAngle = cos(Angle*math::DEG);
00399 T cosAngleInv = 1.0f - cosAngle;
00400
00401 rotMatrixRow1.X = Axis.X*Axis.X + cosAngle*(1.0f - Axis.X*Axis.X);
00402 rotMatrixRow1.Y = Axis.X*Axis.Y*cosAngleInv - sinAngle*Axis.Z;
00403 rotMatrixRow1.Z = Axis.X*Axis.Z*cosAngleInv + sinAngle*Axis.Y;
00404
00405 rotMatrixRow2.X = Axis.X*Axis.Y*cosAngleInv + sinAngle*Axis.Z;
00406 rotMatrixRow2.Y = Axis.Y*Axis.Y + cosAngle*(1.0f - Axis.Y*Axis.Y);
00407 rotMatrixRow2.Z = Axis.Y*Axis.Z*cosAngleInv - sinAngle*Axis.X;
00408
00409 rotMatrixRow3.X = Axis.X*Axis.Z*cosAngleInv - sinAngle*Axis.Y;
00410 rotMatrixRow3.Y = Axis.Y*Axis.Z*cosAngleInv + sinAngle*Axis.X;
00411 rotMatrixRow3.Z = Axis.Z*Axis.Z + cosAngle*(1.0f - Axis.Z*Axis.Z);
00412
00413 return vector3d<T>(
00414 dot(rotMatrixRow1),
00415 dot(rotMatrixRow2),
00416 dot(rotMatrixRow3)
00417 );
00418 }
00419
00421 inline EAxisTypes getAxisType() const
00422 {
00423 const dim::vector3d<T> AbsDir(getAbs());
00424
00425 if (AbsDir.X >= AbsDir.Y && AbsDir.X >= AbsDir.Z)
00426 return (X > 0 ? AXIS_X_POSITIVE : AXIS_X_NEGATIVE);
00427 else if (AbsDir.Y >= AbsDir.X && AbsDir.Y >= AbsDir.Z)
00428 return (Y > 0 ? AXIS_Y_POSITIVE : AXIS_Y_NEGATIVE);
00429
00430 return (Z > 0 ? AXIS_Z_POSITIVE : AXIS_Z_NEGATIVE);
00431 }
00432
00434 inline vector3d<T> getNormal() const
00435 {
00436 if (X > Y && X > Z)
00437 return vector3d<T>(Y, -X, 0);
00438 else if (Y > X && Y > Z)
00439 return vector3d<T>(0, Z, -Y);
00440 return vector3d<T>(-Z, 0, X);
00441 }
00442
00444 inline T getMin() const
00445 {
00446 if (X <= Y && X <= Z) return X;
00447 if (Y <= X && Y <= Z) return Y;
00448 return Z;
00449 }
00451 inline T getMax() const
00452 {
00453 if (X >= Y && X >= Z) return X;
00454 if (Y >= X && Y >= Z) return Y;
00455 return Z;
00456 }
00457
00459 inline T getVolume() const
00460 {
00461 return X*Y*Z;
00462 }
00463
00471 inline vector3d<T> getCoord() const
00472 {
00473 return *this;
00474 }
00475
00476 template <typename B> inline vector3d<B> cast() const
00477 {
00478 return vector3d<B>(static_cast<B>(X), static_cast<B>(Y), static_cast<B>(Z));
00479 }
00480
00481 static inline bool isPointOnSameSide(
00482 const vector3d<T> &P1, const vector3d<T> &P2, const vector3d<T> &A, const vector3d<T> &B)
00483 {
00484 vector3d<T> Difference(B - A);
00485 vector3d<T> P3 = Difference.cross(P1 - A);
00486 vector3d<T> P4 = Difference.cross(P2 - A);
00487 return P3.dot(P4) >= T(0);
00488 }
00489
00490
00491
00492 T X, Y, Z;
00493
00494 };
00495
00496 typedef vector3d<s32> vector3di;
00497 typedef vector3d<f32> vector3df;
00498
00499
00500
00501
00502
00503
00505 template <typename T> class vector4d : public vector3d<T>
00506 {
00507
00508 public:
00509
00510 vector4d() : vector3d<T>(), W(1)
00511 {
00512 }
00513 vector4d(T Size) : vector3d<T>(Size), W(1)
00514 {
00515 }
00516 vector4d(T VecX, T VecY, T VecZ, T VecW = static_cast<T>(1)) : vector3d<T>(VecX, VecY, VecZ), W(VecW)
00517 {
00518 }
00519 vector4d(const vector3d<T> &other, T VecW = static_cast<T>(1)) : vector3d<T>(other.X, other.Y, other.Z), W(VecW)
00520 {
00521 }
00522 vector4d(const vector4d<T> &other) : vector3d<T>(other.X, other.Y, other.Z), W(other.W)
00523 {
00524 }
00525 ~vector4d()
00526 {
00527 }
00528
00529
00530
00531 T W;
00532
00533 };
00534
00535 template <typename T> vector3d<T>::vector3d(const vector4d<T> &Other) :
00536 X(Other.X),
00537 Y(Other.Y),
00538 Z(Other.Z)
00539 {
00540 }
00541
00542 typedef vector4d<s32> vector4di;
00543 typedef vector4d<f32> vector4df;
00544
00545
00546 }
00547
00548 }
00549
00550
00551 #endif
00552
00553
00554
00555