CSC8503_Advanced_Game_Technologies / CSC8503 / CSC8503Common / PhysicsObject.h
PhysicsObject.h
Raw
#pragma once
#include "../../Common/Vector3.h"
#include "../../Common/Matrix3.h"
#include <deque>

using namespace NCL::Maths;

namespace NCL {

	enum CollisionResolution { Impulse = 1, Spring = 2, Collect = 4, Jelly = 8, Snow = 16 };

	class CollisionVolume;
	
	namespace CSC8503 {
		class Transform;

		class PhysicsObject {
		public:
			PhysicsObject(Transform* parentTransform, const CollisionVolume* parentVolume);
			~PhysicsObject();

			Vector3 GetLinearVelocity() const {
				return linearVelocity;
			}

			Vector3 GetAngularVelocity() const {
				return angularVelocity;
			}

			float GetElasticity() const
			{
				return elasticity;
			}

			float GetBuoyancy() const
			{
				return buoyancy;
			}

			Vector3 GetTorque() const {
				return torque;
			}

			Vector3 GetForce() const {
				return force;
			}

			void SetInverseMass(float invMass) {
				inverseMass = invMass;
			}

			float GetInverseMass() const {
				return inverseMass;
			}

			void ApplyAngularImpulse(const Vector3& force);
			void ApplyLinearImpulse(const Vector3& force);

			void AddForce(const Vector3& force);

			void AddForceAtPosition(const Vector3& force, const Vector3& position);
			void AddForceAtRelativePosition(const Vector3& addedForce, const Vector3& position);

			void AddTorque(const Vector3& torque);


			void ClearForces();

			void SetLinearVelocity(const Vector3& v) {
				linearVelocity = v;
			}

			void SetAngularVelocity(const Vector3& v) {
				angularVelocity = v;
			}

			void SetElasticity(const float& e)
			{
				elasticity = e;
			}

			void SetBuoyancy(const float& b)
			{
				buoyancy = b;
			}

			const bool IsAffectedByGravity() const
			{
				return affectedByGravity;
			}

			void SetGravityAffinity(bool value)
			{
				affectedByGravity = value;
			}

			void SetCollisionResolution(const int value)
			{
				collisionResolution = value;
			}

			int GetCollisionResolution() const
			{
				return collisionResolution;
			}

			bool IsSleeping() const {
				return isSleeping;
			}

			void SetSleep(bool sleepState) {
				isSleeping = sleepState;

				if (!sleepState) {
					positionDeltaQueue.clear();
				}
			}

			void SetSnow(const bool& s) { isSnow = s; }
			bool GetSnow() const { return isSnow; }

			void AddPositionDelta(const Vector3& positionDelta) {
				if (inverseMass - FLT_EPSILON < 0.0f) {
					return;
				}

				positionDeltaQueue.push_front(positionDelta);
				Vector3 posDeltaAvg = Vector3(0.0f, 0.0f, 0.0f);

				for (Vector3 posDelta : positionDeltaQueue) {
					posDeltaAvg += posDelta;
				}

				const size_t queueSize = positionDeltaQueue.size();

				if (queueSize >= 5) {
					posDeltaAvg /= queueSize;
					isSleeping = posDeltaAvg.GetAbsMaxElement() < 0.0005f;

					positionDeltaQueue.pop_back();
				}
			}

			void InitCubeInertia();
			void InitSphereInertia();
			void InitHollowSphereInertia();

			void UpdateInertiaTensor();

			Matrix3 GetInertiaTensor() const {
				return inverseInteriaTensor;
			}

		protected:
			const CollisionVolume* volume;
			Transform*		transform;

			float inverseMass;
			float elasticity;
			float friction;
			float buoyancy;
			int collisionResolution;
			bool affectedByGravity;

			//linear stuff
			Vector3 linearVelocity;
			Vector3 force;
			

			//angular stuff
			Vector3 angularVelocity;
			Vector3 torque;
			Vector3 inverseInertia;
			Matrix3 inverseInteriaTensor;

			std::deque<Vector3> positionDeltaQueue;
			bool isSleeping = inverseMass == 0.0f;

			bool isSnow;
		};
	}
}