Вектор

Ноябрь 6, 2007

При разработке игр, наиболее часто используется тип, представляющий собой математический Вектор. Им обозначают точку в пространстве, направление движения, смещение и т.д. Во многих примерах, представленных здесь, я буду использовать нижеследующую реализацию вектора.

Реализации

namespace NShared 
{
	inline bool isNaN(float v) { return _isnan(v)!=0; }
	
	class Vector4
	{
	public:

		float x, y, z, w;

		Vector4(void) {
			this->x=0; this->y=0; this->z=0; this->w=1;
		}

		Vector4(float x, float y, float z=0, float w=1) {
			this->x=x; this->y=y; this->z=z; this->w=w;
		}

		inline void clear(void) {
			x=0.0f; y=0.0f; z=0.0f; w=1.0f;
		}

		inline float* ptr() { return &x ; } 

		inline const float* ptr() const { return &x ; } 

		inline bool operator == (const Vector4& v) const { 
			return x==v.x && y==v.y && z==v.z && w==v.w; 
		}

		inline bool operator != (const Vector4& v) const {
			return x!=v.x || y!=v.y || z!=v.z || w!=v.w; 
		}

		inline const Vector4& set(float x=0, float y=0, float z=0, float w=1) {
			this->x=x; this->y=y; this->z=z; this->w=w;
			return (*this);
		}
		
		inline bool isValid() const { return !isNaN(); }
		inline bool isNaN() const { 
			return NShared::isNaN(x) || NShared::isNaN(y) || NShared::isNaN(z);
		}

		/// Скалярное произведение
		inline float operator * (const Vector4& v) const {
			return x*v.x+y*v.y+z*v.z ;
		}

		/// Векторное произведение
		inline const Vector4 operator ^ (const Vector4& v) const {
			return Vector4(y*v.z-z*v.y,
				z*v.x-x*v.z ,
				x*v.y-y*v.x, 1);
		}

		/// Умножение вектора на число
		inline Vector4 operator * (float v) const {
			return Vector4(x*v, y*v, z*v, w);
		}

		/// Умножение вектора на число
		inline Vector4& operator *= (float v) {
			x*=v;
			y*=v;
			z*=v;
			return *this;
		}

		/// Деление вектора на число
		inline Vector4 operator / (float v) const {
			return Vector4(x/v, y/v, z/v, w);
		}

		/// Деление вектора на число
		inline Vector4& operator /= (float v) {
			x/=v;
			y/=v;
			z/=v;
			return *this;
		}

		/// Сложение векторов
		inline Vector4 operator + (const Vector4& v) const {
			return Vector4(x+v.x, y+v.y,
				z+v.z, w/*+v.w*/);
		}

		/// Сложение векторов
		inline Vector4& operator += (const Vector4& v) {
			x += v.x;
			y += v.y;
			z += v.z;
			return *this;
		}

		/// Вычитание векторов
		inline Vector4 operator - (const Vector4& v) const {
			return Vector4(x-v.x, y-v.y,
				z-v.z, w );
		}

		/// Вычитание векторов
		inline Vector4& operator -= (const Vector4& v) {
			x-=v.x;
			y-=v.y;
			z-=v.z;
			return *this;
		}

		/// Negation operator. Returns the negative of the Vector4.
		inline const Vector4 operator - () const {
			return Vector4 (-x, -y, -z, /*-*/w);
		}

		/// Длина вектора
		inline float length() const {
			return sqrtf( x*x + y*y + z*z );
		}

		/// квадрат длины вектора
		inline float length2() const {
			return x*x + y*y + z*z;
		}

		/// Нормализация вектора (преобразуем вектор в единичный)
		const Vector4& normalize(void) {
			float norm = Vector4::length();
			if (norm>0.0f) {
				float inv = 1.0f/norm;
				x *= inv;
				y *= inv;
				z *= inv;
			}
			return( *this);
		}

		/// Возвращаем единичный вектор, полученный из этого
		inline Vector4 getNormalized(void) const {
			Vector4 v = (*this);
			v.normalize();
			return v;
		}

		/// поворот вектора относительно оси X
		const Vector4& rotateX(float ang) {
			static float c, s;
			static float a;
			a = degreesToRadians(ang);
			c=cosf(a);
			s=sinf(a);
			if(NShared::isNaN(c))
				c=0;
			if(NShared::isNaN(s))
				s=0;
			static float ny, nz;
			ny = c*y-s*z;
			nz = s*y+c*z;
			y = ny;
			z = nz;
			return *this;
		}

		/// поворот вектора относительно оси Y
		const Vector4& rotateY(float ang) {
			static float c, s;
			static float a;
			a = degreesToRadians(ang);
			c=cosf(a);
			s=sinf(a);
			if(NShared::isNaN(c))
				c=0;
			if(NShared::isNaN(s))
				s=0;

			static float nx, nz;
			nx = c*x+s*z;
			nz = -s*x+c*z;
			x = nx;
			z = nz;
			return *this;

		}

		/// поворот вектора относительно оси Z
		const Vector4& rotateZ(float ang) {
			static float c, s;
			static float a;
			a = degreesToRadians(ang);
			c=cosf(a);
			s=sinf(a);
			
			if(NShared::isNaN(c))
				c=0;
			if(NShared::isNaN(s))
				s=0;
			static float nx, ny;
			nx = c*x-s*y;
			ny = s*x+c*y;
			x = nx;
			y = ny;
			return *this;
		}

	}; 
}
			

All content copyright (c) 2012 Vladislav Litunovskiy. All Rights Reserved.