1 /* 2 Copyright (C) 2007, 2010 - Bit-Blot 3 4 This file is part of Aquaria. 5 6 Aquaria is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License 8 as published by the Free Software Foundation; either version 2 9 of the License, or (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 15 See the GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 */ 21 #ifndef BBGE_VECTOR_H 22 #define BBGE_VECTOR_H 23 24 #include <cmath> 25 #include <float.h> 26 #include <vector> 27 #include "Event.h" 28 29 #ifdef BBGE_BUILD_DIRECTX 30 #include <d3dx9.h> 31 #endif 32 typedef float scalar_t; 33 34 class Vector 35 { 36 public: 37 scalar_t x; 38 scalar_t y; 39 scalar_t z; // x,y,z coordinates 40 x(a)41 Vector(scalar_t a = 0, scalar_t b = 0, scalar_t c = 0) : x(a), y(b), z(c) {} Vector(const Vector & vec)42 Vector(const Vector &vec) : x(vec.x), y(vec.y), z(vec.z) {} 43 44 getv(float * v)45 float inline *getv(float *v) const 46 { 47 v[0] = x; v[1] = y; v[2] = z; 48 return v; 49 } 50 getv4(float * v,float param)51 float inline *getv4(float *v, float param) const 52 { 53 v[0] = x; v[1] = y; v[2] = z; v[3] = param; 54 return v; 55 } 56 57 // vector assignment 58 const Vector &operator=(const Vector &vec) 59 { 60 x = vec.x; 61 y = vec.y; 62 z = vec.z; 63 64 return *this; 65 } 66 67 // vecector equality 68 bool operator==(const Vector &vec) const 69 { 70 return ((x == vec.x) && (y == vec.y) && (z == vec.z)); 71 } 72 73 // vecector inequality 74 bool operator!=(const Vector &vec) const 75 { 76 return !(*this == vec); 77 } 78 79 // vector add 80 const Vector operator+(const Vector &vec) const 81 { 82 return Vector(x + vec.x, y + vec.y, z + vec.z); 83 } 84 85 // vector add (opposite of negation) 86 const Vector operator+() const 87 { 88 return Vector(*this); 89 } 90 91 // vector increment 92 const Vector& operator+=(const Vector& vec) 93 { x += vec.x; 94 y += vec.y; 95 z += vec.z; 96 return *this; 97 } 98 99 // vector subtraction 100 const Vector operator-(const Vector& vec) const 101 { 102 return Vector(x - vec.x, y - vec.y, z - vec.z); 103 } 104 105 // vector negation 106 const Vector operator-() const 107 { 108 return Vector(-x, -y, -z); 109 } 110 111 // vector decrement 112 const Vector &operator-=(const Vector& vec) 113 { 114 x -= vec.x; 115 y -= vec.y; 116 z -= vec.z; 117 118 return *this; 119 } 120 121 // scalar self-multiply 122 const Vector &operator*=(const scalar_t &s) 123 { 124 x *= s; 125 y *= s; 126 z *= s; 127 128 return *this; 129 } 130 131 // scalar self-divecide 132 const Vector &operator/=(const scalar_t &s) 133 { 134 const float recip = 1/s; // for speed, one divecision 135 136 x *= recip; 137 y *= recip; 138 z *= recip; 139 140 return *this; 141 } 142 143 // vector self-divide 144 const Vector &operator/=(const Vector &v) 145 { 146 x /= v.x; 147 y /= v.y; 148 z /= v.z; 149 150 return *this; 151 } 152 153 const Vector &operator*=(const Vector &v) 154 { 155 x *= v.x; 156 y *= v.y; 157 z *= v.z; 158 159 return *this; 160 } 161 162 163 // post multiply by scalar 164 const Vector operator*(const scalar_t &s) const 165 { 166 return Vector(x*s, y*s, z*s); 167 } 168 169 // post multiply by Vector 170 const Vector operator*(const Vector &v) const 171 { 172 return Vector(x*v.x, y*v.y, z*v.z); 173 } 174 175 // pre multiply by scalar 176 friend inline const Vector operator*(const scalar_t &s, const Vector &vec) 177 { 178 return vec*s; 179 } 180 181 /* friend inline const Vector operator*(const Vector &vec, const scalar_t &s) 182 { 183 return Vector(vec.x*s, vec.y*s, vec.z*s); 184 } 185 */ 186 // divecide by scalar 187 const Vector operator/(scalar_t s) const 188 { 189 s = 1/s; 190 191 return Vector(s*x, s*y, s*z); 192 } 193 194 195 // cross product CrossProduct(const Vector & vec)196 const Vector CrossProduct(const Vector &vec) const 197 { 198 return Vector(y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x); 199 } 200 getPerpendicularLeft()201 inline Vector getPerpendicularLeft() 202 { 203 return Vector(-y, x); 204 } 205 getPerpendicularRight()206 inline Vector getPerpendicularRight() 207 { 208 return Vector(y, -x); 209 } 210 211 // cross product 212 const Vector operator^(const Vector &vec) const 213 { 214 return Vector(y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x); 215 } 216 217 // dot product dot(const Vector & vec)218 inline scalar_t dot(const Vector &vec) const 219 { 220 return x*vec.x + y*vec.y + z*vec.z; 221 } 222 dot2D(const Vector & vec)223 inline scalar_t dot2D(const Vector &vec) const 224 { 225 return x*vec.x + y*vec.y; 226 } 227 228 // dot product 229 scalar_t operator%(const Vector &vec) const 230 { 231 return x*vec.x + y*vec.x + z*vec.z; 232 } 233 234 235 // length of vector getLength3D()236 inline scalar_t getLength3D() const 237 { 238 return (scalar_t)sqrtf(x*x + y*y + z*z); 239 } getLength2D()240 inline scalar_t getLength2D() const 241 { 242 return (scalar_t)sqrtf(x*x + y*y); 243 } 244 245 // return the unit vector unitVector3D()246 inline const Vector unitVector3D() const 247 { 248 return (*this) * (1/getLength3D()); 249 } 250 251 // normalize this vector normalize3D()252 inline void normalize3D() 253 { 254 if (x == 0 && y == 0 && z == 0) 255 { 256 //debugLog("Normalizing 0 vector"); 257 x = y = z = 0; 258 } 259 else 260 { 261 (*this) *= 1/getLength3D(); 262 } 263 } normalize2D()264 inline void normalize2D() 265 { 266 if (x == 0 && y == 0) 267 { 268 //debugLog("Normalizing 0 vector"); 269 x = y = z= 0; 270 } 271 else 272 { 273 (*this) *= 1/getLength2D(); 274 } 275 } 276 277 scalar_t operator!() const 278 { 279 return sqrtf(x*x + y*y + z*z); 280 } 281 282 /* 283 // return vector with specified length 284 const Vector operator | (const scalar_t length) const 285 { 286 return *this * (length / !(*this)); 287 } 288 289 // set length of vector equal to length 290 const Vector& operator |= (const float length) 291 { 292 (*this).setLength2D(length); 293 return *this; 294 } 295 */ 296 setLength3D(const float l)297 inline void setLength3D(const float l) 298 { 299 // IGNORE !! 300 if (l == 0) 301 { 302 //debugLog("setLength3D divide by 0"); 303 } 304 else 305 { 306 float len = getLength3D(); 307 this->x *= (l/len); 308 this->y *= (l/len); 309 this->z *= (l/len); 310 } 311 } setLength2D(const float l)312 inline void setLength2D(const float l) 313 { 314 float len = getLength2D(); 315 if (len == 0) 316 { 317 //debugLog("divide by zero!"); 318 } 319 else 320 { 321 this->x *= (l/len); 322 this->y *= (l/len); 323 } 324 //this->z = 0; 325 } 326 327 // return angle between two vectors Angle(const Vector & normal)328 inline scalar_t Angle(const Vector& normal) const 329 { 330 return acosf(*this % normal); 331 } 332 333 /* 334 inline scalar_t cheatLen() const 335 { 336 return (x*x + y*y + z*z); 337 } 338 inline scalar_t cheatLen2D() const 339 { 340 return (x*x + y*y); 341 } 342 inline scalar_t getCheatLength3D() const; 343 */ 344 isLength2DIn(float radius)345 inline bool isLength2DIn(float radius) const 346 { 347 return (x*x + y*y) <= (radius*radius); 348 } 349 350 // reflect this vector off surface with normal vector 351 /* 352 const Vector inline Reflection(const Vector& normal) const 353 { 354 const Vector vec(*this | 1); // normalize this vector 355 return (vec - normal * 2.0f * (vec % normal)) * !*this; 356 } 357 */ 358 setZero()359 inline void setZero() 360 { 361 this->x = this->y = this->z = 0; 362 } getSquaredLength2D()363 inline scalar_t getSquaredLength2D() const 364 { 365 return (x*x) + (y*y); 366 } isZero()367 inline bool isZero() const 368 { 369 return x==0 && y==0 && z==0; 370 } 371 isNan()372 inline bool isNan() const 373 { 374 #ifdef BBGE_BUILD_WINDOWS 375 return _isnan(x) || _isnan(y) || _isnan(z); 376 #elif defined(BBGE_BUILD_UNIX) 377 return std::isnan(x) || std::isnan(y) || std::isnan(z); 378 #else 379 return false; 380 #endif 381 } 382 capLength2D(const float l)383 inline void capLength2D(const float l) 384 { 385 if (!isLength2DIn(l)) setLength2D(l); 386 } capRotZ360()387 inline void capRotZ360() 388 { 389 while (z > 360) 390 z -= 360; 391 while (z < 0) 392 z += 360; 393 } 394 395 #ifdef BBGE_BUILD_DIRECTX getD3DColor(float alpha)396 const D3DCOLOR getD3DColor(float alpha) 397 { 398 return D3DCOLOR_RGBA(int(x*255), int(y*255), int(z*255), int(alpha*255)); 399 } 400 #endif 401 void rotate2DRad(float rad); 402 void rotate2D360(float angle); 403 }; 404 405 406 class VectorPathNode 407 { 408 public: VectorPathNode()409 VectorPathNode() { percent = 0; } 410 411 Vector value; 412 float percent; 413 }; 414 415 class VectorPath 416 { 417 public: 418 void flip(); 419 void clear(); 420 void addPathNode(Vector v, float p); 421 Vector getValue(float percent); getNumPathNodes()422 int getNumPathNodes() { return pathNodes.size(); } resizePathNodes(int sz)423 void resizePathNodes(int sz) { pathNodes.resize(sz); } getPathNode(int i)424 VectorPathNode *getPathNode(int i) { if (i<getNumPathNodes() && i >= 0) return &pathNodes[i]; return 0; } 425 void cut(int n); 426 void splice(const VectorPath &path, int sz); 427 void prepend(const VectorPath &path); 428 void append(const VectorPath &path); 429 void removeNode(unsigned int i); 430 void calculatePercentages(); 431 float getLength(); 432 void realPercentageCalc(); 433 void removeNodes(unsigned int startInclusive, unsigned int endInclusive); 434 float getSubSectionLength(int startIncl, int endIncl); 435 protected: 436 std::vector <VectorPathNode> pathNodes; 437 }; 438 439 440 class InterpolatedVector; 441 struct InterpolatedVectorData 442 { InterpolatedVectorDataInterpolatedVectorData443 InterpolatedVectorData() 444 { 445 interpolating = false; 446 pingPong = false; 447 loopType = 0; 448 pathTimer = 0; 449 pathTime = 0; 450 pathSpeed = 1; 451 pathTimeMultiplier = 1; 452 timePassed = 0; 453 timePeriod = 0; 454 //fakeTimePassed = 0; 455 ease = false; 456 followingPath = false; 457 } 458 459 Vector from; 460 Vector target; 461 462 VectorPath path; 463 464 int loopType; 465 466 float pathTimer, pathTime; 467 float pathSpeed; 468 float pathTimeMultiplier; 469 float timePassed, timePeriod; 470 471 bool interpolating; 472 bool pingPong; 473 bool ease; 474 bool followingPath; 475 }; 476 477 478 // This struct is used to keep all of the interpolation-specific data out 479 // of the global InterpolatedVector class, so that we don't waste memory on 480 // non-interpolated vectors. 481 class InterpolatedVector : public Vector 482 { 483 public: Vector(a,b,c)484 InterpolatedVector(scalar_t a = 0, scalar_t b = 0, scalar_t c = 0) : Vector(a,b,c), data(NULL) {} InterpolatedVector(const Vector & vec)485 InterpolatedVector(const Vector &vec) : Vector(vec), data(NULL) {} ~InterpolatedVector()486 ~InterpolatedVector() {delete data;} 487 InterpolatedVector(const InterpolatedVector & vec)488 InterpolatedVector(const InterpolatedVector &vec) 489 { 490 x = vec.x; 491 y = vec.y; 492 z = vec.z; 493 if (vec.data) 494 data = new InterpolatedVectorData(*vec.data); 495 else 496 data = NULL; 497 } 498 InterpolatedVector &operator=(const InterpolatedVector &vec) 499 { 500 x = vec.x; 501 y = vec.y; 502 z = vec.z; 503 if (vec.data) 504 { 505 if (data) 506 *data = *vec.data; 507 else 508 data = new InterpolatedVectorData(*vec.data); 509 } 510 else 511 { 512 delete data; 513 data = NULL; 514 } 515 return *this; 516 } 517 518 enum InterpolateToFlag { NONE=0, IS_LOOPING }; 519 float interpolateTo (Vector vec, float timePeriod, int loopType = 0, bool pingPong = false, bool ease = false, InterpolateToFlag flag = NONE); update(float dt)520 void inline update(float dt) 521 { 522 if (!data) 523 return; 524 525 if (isFollowingPath()) 526 { 527 updatePath(dt); 528 } 529 if (isInterpolating()) 530 { 531 doInterpolate(dt); 532 } 533 } 534 535 void doInterpolate(float dt); 536 isInterpolating()537 inline bool isInterpolating() const 538 { 539 return data && data->interpolating; 540 } 541 542 void startPath(float time, float ease=0); 543 void startSpeedPath(float speed); 544 void stopPath(); 545 void resumePath(); 546 547 void updatePath(float dt); 548 549 void stop(); 550 551 float getPercentDone(); 552 isFollowingPath()553 inline bool isFollowingPath() const 554 { 555 return data && data->followingPath; 556 } 557 558 // for faking a single value getValue()559 inline float getValue() const 560 { 561 return x; 562 } 563 564 565 // We never allocate this if the vector isn't used for 566 // interpolation, which saves a _lot_ of memory. 567 InterpolatedVectorData *data; 568 ensureData(void)569 inline InterpolatedVectorData *ensureData(void) 570 { 571 if (!data) 572 data = new InterpolatedVectorData; 573 return data; 574 } 575 }; 576 577 Vector getRotatedVector(const Vector &vec, float rot); 578 579 Vector lerp(const Vector &v1, const Vector &v2, float dt, int lerpType); 580 581 #endif // BBGE_VECTOR_H 582