CSC8503_Advanced_Game_Technologies / Common / Vector4.h
Vector4.h
Raw
/*
Part of Newcastle University's Game Engineering source code.

Use as you see fit!

Comments and queries to: richard-gordon.davison AT ncl.ac.uk
https://research.ncl.ac.uk/game/
*/
#pragma once
#include <iostream>

namespace NCL {
	namespace Maths {
		class Vector3;
		class Vector2;

		class Vector4 {

		public:
			union {
				struct {
					float x;
					float y;
					float z;
					float w;
				};
				float array[4];
			};

		public:
			constexpr Vector4(void) : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}

			constexpr Vector4(float xVal, float yVal, float zVal, float wVal) : x(xVal), y(yVal), z(zVal), w(wVal) {}

			Vector4(const Vector3& v3, float w = 0.0f);
			Vector4(const Vector2& v2, float z = 0.0f, float w = 0.0f);

			~Vector4(void) {}

			Vector4 Normalised() const {
				Vector4 temp(x, y, z, w);
				temp.Normalise();
				return temp;
			}

			void			Normalise() {
				float length = Length();

				if (length != 0.0f) {
					length = 1.0f / length;
					x = x * length;
					y = y * length;
					z = z * length;
					w = w * length;
				}
			}

			float	Length() const {
				return sqrt((x*x) + (y*y) + (z*z) + (w * w));
			}

			constexpr float	LengthSquared() const {
				return ((x*x) + (y*y) + (z*z) + (w * w));
			}

			constexpr float		GetMaxElement() const {
				float v = x;
				if (y > v) {
					v = y;
				}
				if (z > v) {
					v = z;
				}
				if (w > v) {
					v = w;
				}
				return v;
			}

			float		GetAbsMaxElement() const {
				float v = abs(x);
				if (abs(y) > v) {
					v = abs(y);
				}
				if (abs(z) > v) {
					v = abs(z);
				}
				if (abs(w) > v) {
					v = abs(w);
				}
				return v;
			}

			static float	Dot(const Vector4 &a, const Vector4 &b) {
				return (a.x*b.x) + (a.y*b.y) + (a.z*b.z) + (a.w*b.w);
			}

			inline Vector4  operator+(const Vector4  &a) const {
				return Vector4(x + a.x, y + a.y, z + a.z, w + a.w);
			}

			inline Vector4  operator-(const Vector4  &a) const {
				return Vector4(x - a.x, y - a.y, z - a.z, w - a.w);
			}

			inline Vector4  operator-() const {
				return Vector4(-x, -y, -z, -w);
			}

			inline Vector4  operator*(float a)	const {
				return Vector4(x * a, y * a, z * a, w * a);
			}

			inline Vector4  operator*(const Vector4  &a) const {
				return Vector4(x * a.x, y * a.y, z * a.z, w * a.w);
			}

			inline Vector4  operator/(const Vector4  &a) const {
				return Vector4(x / a.x, y / a.y, z / a.z, w / a.w);
			};

			inline Vector4  operator/(float v) const {
				return Vector4(x / v, y / v, z / v, w / v);
			};

			inline constexpr void operator+=(const Vector4  &a) {
				x += a.x;
				y += a.y;
				z += a.z;
				w += a.w;
			}

			inline void operator-=(const Vector4  &a) {
				x -= a.x;
				y -= a.y;
				z -= a.z;
				w -= a.w;
			}


			inline void operator*=(const Vector4  &a) {
				x *= a.x;
				y *= a.y;
				z *= a.z;
				w *= a.w;
			}

			inline void operator/=(const Vector4  &a) {
				x /= a.x;
				y /= a.y;
				z /= a.z;
				w /= a.w;
			}

			inline void operator*=(float f) {
				x *= f;
				y *= f;
				z *= f;
				w *= f;
			}

			inline void operator/=(float f) {
				x /= f;
				y /= f;
				z /= f;
				w /= f;
			}

			inline float operator[](int i) const {
				return array[i];
			}

			inline float& operator[](int i) {
				return array[i];
			}

			inline bool	operator==(const Vector4 &A)const { return (A.x == x && A.y == y && A.z == z && A.w == w) ? true : false; };
			inline bool	operator!=(const Vector4 &A)const { return (A.x == x && A.y == y && A.z == z && A.w == w) ? false : true; };

			inline friend std::ostream& operator<<(std::ostream& o, const Vector4& v) {
				o << "Vector4(" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << std::endl;
				return o;
			}
		};

		static Vector4 COLOUR_BLACK(0, 0, 0, 1.0f);
		static Vector4 COLOUR_WHITE(1, 1, 1, 1.0f);
		static Vector4 HOMOGENEOUS(0, 0, 0, 1.0f);
	}
}