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