Browse Source

added flags

vlod 1 year ago
parent
commit
da9cc20517

+ 15 - 11
Pika/gameplay/containers/physicsTest/physicsTest.h

@@ -37,11 +37,13 @@ struct PhysicsTest: public Container
 	{
 		renderer.create(requestedInfo.requestedFBO.fbo);
 	
-		for (int i = 0; i < 0; i++)
+		physicsEngine.simulationphysicsSettings.gravity = glm::vec2(0, 9.81) * 100.f;
+
+		for (int i = 0; i < 10; i++)
 		{
 			//if (i == 1) { mass = 0; }
 
-			if (1)
+			if (0)
 			{
 				float w = rand() % 100 + 20;
 				float h = rand() % 100 + 20;
@@ -69,13 +71,15 @@ struct PhysicsTest: public Container
 			{-25, 25},
 			{-40, -10},
 		};
-		physicsEngine.addBody({500, 200}, ph2d::createConvexPolygonCollider(shape, 5));
+		//physicsEngine.addBody({500, 200}, ph2d::createConvexPolygonCollider(shape, 5));
 
 
 		//physicsEngine.addBody({500, 1100}, 
 		//	ph2d::createBoxCollider({1100, 10}));
 
-		//physicsEngine.addBody({500, 500}, ph2d::createBoxCollider({300, 100}));
+		physicsEngine.addBody({500, 500}, ph2d::createBoxCollider({400, 50}));
+		//physicsEngine.bodies.back().flags.setFreezePosition();
+		physicsEngine.bodies.back().flags.setFreezeRotation();
 
 		//physicsEngine.addBody({1, 800}, ph2d::createBoxCollider({800, 50}));
 		//physicsEngine.bodies[1].motionState.mass = 0;
@@ -220,7 +224,7 @@ struct PhysicsTest: public Container
 			force *= physicsEngine.bodies[selected].motionState.mass;
 			force *= 2.f;
 
-			physicsEngine.bodies[selected].motionState.applyImpulseWorldPosition(force,
+			physicsEngine.bodies[selected].applyImpulseWorldPosition(force,
 				//physicsEngine.bodies[selected].motionState.pos
 				pressedPosition
 			);
@@ -236,12 +240,12 @@ struct PhysicsTest: public Container
 		{
 
 			//gravity
-			if(simulate)
-			for (int i=0; i<physicsEngine.bodies.size(); i++)
-			{
-				if(physicsEngine.bodies[i].motionState.mass != 0 && physicsEngine.bodies[i].motionState.mass != INFINITY)
-					physicsEngine.bodies[i].motionState.acceleration += glm::vec2(0, 9.81) * 100.f;
-			}
+			//if(simulate)
+			//for (int i=0; i<physicsEngine.bodies.size(); i++)
+			//{
+			//	if(physicsEngine.bodies[i].motionState.mass != 0 && physicsEngine.bodies[i].motionState.mass != INFINITY)
+			//		physicsEngine.bodies[i].motionState.acceleration += glm::vec2(0, 9.81) * 100.f;
+			//}
 
 			if (simulate)
 			{

+ 2 - 6
Pika/resources/logs.txt

@@ -1,6 +1,2 @@
-#2024-11-22 16:16:51: Created container: PhysicsTest
-#2024-11-22 16:17:13: Reloaded dll
-#2024-11-22 16:17:19: Reloaded dll
-#2024-11-22 16:17:32: Reloaded dll
-#2024-11-22 16:17:37: Reloaded dll
-#2024-11-22 16:19:00: Destroyed continer: PhysicsTest #1
+#2024-11-22 18:47:46: Created container: PhysicsTest
+#2024-11-22 18:47:49: Destroyed continer: PhysicsTest #1

+ 0 - 0
Pika/thirdparty/ph2d/include/ph2d/ph2d.cpp


+ 76 - 4
Pika/thirdparty/ph2d/include/ph2d/ph2d.h

@@ -21,11 +21,17 @@
 
 #include <glm/glm.hpp>
 #include <vector>
+#include <bitset>
 
 constexpr static int PH2D_MAX_CONVEX_SHAPE_POINTS = 12;
 
+
 namespace ph2d
 {
+
+	using ph2dUserData = std::uint64_t;
+	using ph2dBodyId = std::uint32_t;
+	
 	struct LineEquation;
 
 
@@ -105,6 +111,42 @@ namespace ph2d
 
 	glm::vec2 rotateAroundPoint(glm::vec2 in, glm::vec2 centerReff, float r);
 
+
+	enum
+	{
+		BodyFlag_freezeX = 0,
+		BodyFlag_freezeY = 1,
+		BodyFlag_freezeRotation = 2,
+		BodyFlag_Sensor = 3,
+
+	};
+
+	struct BodyFlags
+	{
+		std::bitset<8> flags = {};
+
+		//the kinematic body is just a body with frozen rotation and positions!
+		bool isKinematic() { return isFreezeX() && isFreezeY() && isFreezeRotation(); }
+
+		//the kinematic body is just a body with frozen rotation and positions!
+		void setKinematic(bool k = true) { setFreezeX(k); setFreezeY(k); setFreezeRotation(k); }
+
+		bool isFreezeX() const { return flags.test(BodyFlag_freezeX); }
+		void setFreezeX(bool f = true) { flags.set(BodyFlag_freezeX, f); }
+
+		bool isFreezeY() const { return flags.test(BodyFlag_freezeY); }
+		void setFreezeY(bool f = true) { flags.set(BodyFlag_freezeY, f); }
+
+		bool isFreezePosition() const{ return isFreezeX() && isFreezeY(); }
+		void setFreezePosition(bool f = true) { setFreezeX(f); setFreezeY(f); }
+
+		bool isFreezeRotation() const { return flags.test(BodyFlag_freezeRotation); }
+		void setFreezeRotation(bool f = true) { flags.set(BodyFlag_freezeRotation, f); }
+
+		bool isSensor() const { return flags.test(BodyFlag_Sensor); }
+		void setSensor(bool s = true) { flags.set(BodyFlag_Sensor, s); }
+	};
+
 	struct MotionState
 	{
 		glm::vec2 pos = {};
@@ -120,9 +162,9 @@ namespace ph2d
 
 		void setPos(glm::vec2 p) { pos = p; lastPos = p; }
 
-		void applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector);
+		void applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector, BodyFlags flags);
 		
-		void applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos);
+		void applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos, BodyFlags flags);
 
 	};
 
@@ -252,16 +294,30 @@ namespace ph2d
 
 	Collider createConvexPolygonCollider(glm::vec2 *shape, unsigned char count);
 
+
 	struct Body
 	{
+		Collider collider = {};
+		
+		ph2dUserData userData;
+		ph2dBodyId id = 0;
+
 		//we use center position
 		MotionState motionState;
 
-		Collider collider = {};
+		void applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector);
+
+		void applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos);
+
+		glm::vec2 gravityScale = {1,1};
 
 		float elasticity = 0.2;
 		float staticFriction = 0.7;
 		float dynamicFriction = 0.6;
+		float dragScale = 1;
+		float angularDragScale = 1;
+
+		BodyFlags flags;
 
 		AABB getAABB();
 
@@ -276,7 +332,6 @@ namespace ph2d
 		glm::vec2 &normal, glm::vec2 &contactPoint, 
 		glm::vec2 &tangentA, glm::vec2 &tangentB);
 
-
 	struct ManifoldIntersection
 	{
 		glm::vec2 normal = {};
@@ -288,8 +343,23 @@ namespace ph2d
 		unsigned short B = 0;
 	};
 
+	struct SimulationPhysicsSettings
+	{
+		glm::vec2 gravity{0, 9.81};
+		float maxVelocity = 10'000;
+		float minVelocity = 0.1;
+		float minAngularVelocity = 0.01;
+		float maxAcceleration = 10'000;
+		float maxAirDrag = 100;
+		float maxAngularDrag = 100;
+		float airDragCoeficient = 0.1f;
+		float rotationalDragCoeficient = 0.01f;
+	};
+
 	struct PhysicsEngine
 	{
+		ph2dBodyId idCounter = 0;
+
 		std::vector<Body> bodies;
 
 		std::vector<ManifoldIntersection> intersections;
@@ -305,6 +375,8 @@ namespace ph2d
 		float _fixedTimeAccumulated = 0;
 		void runSimulation(float deltaTime);
 
+		SimulationPhysicsSettings simulationphysicsSettings;
+
 		void addBody(glm::vec2 centerPos, Collider collider);
 
 		void addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal);

+ 116 - 37
Pika/thirdparty/ph2d/src/ph2d.cpp

@@ -20,12 +20,6 @@
 #include <iostream>
 #include <algorithm>
 
-//todo per engine
-constexpr static float MAX_VELOCITY = 10'000;
-constexpr static float MIN_VELOCITY = 0.1;
-constexpr static float MIN_ANGULAR_VELOCITY = 0.01;
-constexpr static float MAX_ACCELERATION = 10'000;
-constexpr static float MAX_AIR_DRAG = 100;
 
 void normalizeSafe(glm::vec2 &v)
 {
@@ -278,10 +272,18 @@ namespace ph2d
 		float rotation,
 		float &penetration, glm::vec2 &normal, glm::vec2 &contactPoint)
 	{
+		penetration = 0;
+		normal = {0, 0};
 
+		glm::vec2 corners[PH2D_MAX_CONVEX_SHAPE_POINTS] = {};
+		convexPolygon.getCornersRotated(corners, rotation);
+		int vertexCount = convexPolygon.vertexCount;
 
+		glm::vec2 circleCenter = circle.center();
+		float circleRadius = circle.size.x/2.f;
+		
 
-
+		return true;
 	}
 
 
@@ -1117,45 +1119,71 @@ namespace ph2d
 					tangentB, tangentA);
 			}
 
+		else if (A.collider.type == ph2d::ColliderCircle
+			&& B.collider.type == ph2d::ColliderConvexPolygon
+			)
+			{
+				return CirclevsConvexPolygon(A.getAABB(), B.collider.collider.convexPolygon,
+					B.motionState.pos, B.motionState.rotation, penetration, normal, contactPoint);
+			}
+		else if (A.collider.type == ph2d::ColliderConvexPolygon
+			&& B.collider.type == ph2d::ColliderCircle
+			)
+			{
+				bool rez = CirclevsConvexPolygon(B.getAABB(), A.collider.collider.convexPolygon,
+					A.motionState.pos, A.motionState.rotation, penetration, normal, contactPoint);
+				normal = -normal;
+				return rez;
+			}
+
 
 		return 0;
 	}
 
 	//todo make sure drag can't be stronger than speed!
-	void applyDrag(MotionState &motionState)
+	void applyDrag(MotionState &motionState, float scale, SimulationPhysicsSettings &s)
 	{
-		glm::vec2 dragForce = 0.1f * -motionState.velocity * glm::abs(motionState.velocity) / 2.f;
+		glm::vec2 dragForce = scale * s.airDragCoeficient * -motionState.velocity * glm::abs(motionState.velocity) / 2.f;
+
 		float length = glm::length(dragForce);
 		if (length)
 		{
-			if (length > MAX_AIR_DRAG)
+			if (length > s.maxAirDrag)
 			{
 				dragForce /= length;
-				dragForce *= MAX_AIR_DRAG;
+				dragForce *= s.maxAirDrag;
 			}
 		
 			motionState.acceleration += dragForce;
 		}
 	}
 
-	void applyAngularDrag(MotionState &motionState)
+	//todo delta time
+	void applyAngularDrag(MotionState &motionState, float scale,
+		SimulationPhysicsSettings &s)
 	{
-		float dragForce = 0.02f * -motionState.angularVelocity;
-		if (dragForce > MAX_AIR_DRAG)
+		float dragForce = scale * s.rotationalDragCoeficient * -motionState.angularVelocity;
+		if (dragForce > s.maxAngularDrag)
 		{
-			dragForce = MAX_AIR_DRAG;
+			dragForce = s.maxAngularDrag;
 		}
-		if (dragForce < -MAX_AIR_DRAG)
+		if (dragForce < -s.maxAngularDrag)
 		{
-			dragForce = -MAX_AIR_DRAG;
+			dragForce = -s.maxAngularDrag;
 		}
 		motionState.angularVelocity += dragForce;
 	}
 
-	void integrateForces(MotionState &motionState, float deltaTime)
+	void integrateForces(MotionState &motionState, float deltaTime,
+		SimulationPhysicsSettings &s, BodyFlags flags)
 	{
 
-		if (motionState.mass == 0 || motionState.mass == INFINITY)
+		bool frezeX = flags.isFreezeX();
+		bool frezeY = flags.isFreezeY();
+
+		if (motionState.mass == 0 || motionState.mass == INFINITY
+			|| (frezeX && frezeY)
+			)
 		{
 			motionState.acceleration = {};
 			motionState.velocity = {};
@@ -1175,16 +1203,21 @@ namespace ph2d
 
 			//linear motion
 			motionState.acceleration = glm::clamp(motionState.acceleration,
-				glm::vec2(-MAX_ACCELERATION), glm::vec2(MAX_ACCELERATION));
+				glm::vec2(-s.maxAcceleration), glm::vec2(s.maxAcceleration));
 
 			//Symplectic Euler
 			motionState.velocity += motionState.acceleration * deltaTime * 0.5f;
-			motionState.velocity = glm::clamp(motionState.velocity, glm::vec2(-MAX_VELOCITY), glm::vec2(MAX_VELOCITY));
+			motionState.velocity = glm::clamp(motionState.velocity, glm::vec2(-s.maxVelocity), glm::vec2(s.maxVelocity));
+
+			glm::vec2 toAdd = motionState.velocity * deltaTime;
 
-			motionState.pos += motionState.velocity * deltaTime;
+			if (frezeX) { toAdd.x = 0; motionState.velocity.x = 0; }
+			if (frezeY) { toAdd.y = 0; motionState.velocity.y = 0; }
+
+			motionState.pos += toAdd;
 
 			motionState.velocity += motionState.acceleration * deltaTime * 0.5f;
-			motionState.velocity = glm::clamp(motionState.velocity, glm::vec2(-MAX_VELOCITY), glm::vec2(MAX_VELOCITY));
+			motionState.velocity = glm::clamp(motionState.velocity, glm::vec2(-s.maxVelocity), glm::vec2(s.maxVelocity));
 
 			if (std::fabs(motionState.velocity.x) < 0.00001) { motionState.velocity.x = 0; }
 			if (std::fabs(motionState.velocity.y) < 0.00001) { motionState.velocity.y = 0; }
@@ -1192,7 +1225,8 @@ namespace ph2d
 			motionState.acceleration = {};
 		}
 
-		if (motionState.momentOfInertia == 0 || motionState.momentOfInertia == INFINITY)
+		if (motionState.momentOfInertia == 0 || motionState.momentOfInertia == INFINITY
+			|| flags.isFreezeRotation())
 		{
 			motionState.angularVelocity = 0;
 			motionState.torque = 0;
@@ -1357,23 +1391,29 @@ bool overlap(ph2d::Body &a, ph2d::Body &b)
 
 
 
-void ph2d::MotionState::applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector)
+void ph2d::MotionState::applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector, BodyFlags flags)
 {
+
+
 	if (mass != 0 && mass != INFINITY )
 	{
-		velocity += (1.0f / mass) * impulse;
+		glm::vec2 toAdd = (1.0f / mass) * impulse;
+		if (flags.isFreezeX()) { toAdd.x = 0; }
+		if (flags.isFreezeY()) { toAdd.y = 0; }
+
+		velocity += toAdd;
 	}
 
-	if (momentOfInertia != 0 && momentOfInertia != INFINITY)
+	if (momentOfInertia != 0 && momentOfInertia != INFINITY && !flags.isFreezeRotation())
 	{
 		angularVelocity -= (1.0f / momentOfInertia) * cross(contactVector, impulse) * 0.95f;
 	}
 }
 
-void ph2d::MotionState::applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos)
+void ph2d::MotionState::applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos, BodyFlags flags)
 {
 	glm::vec2 relVector = contactVectorWorldPos - pos;
-	applyImpulseObjectPosition(impulse, relVector);
+	applyImpulseObjectPosition(impulse, relVector, flags);
 }
 
 
@@ -1408,10 +1448,17 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 		auto positionalCorrection = [&](Body &A, Body &B, glm::vec2 n,
 			float penetrationDepth)
 		{
+			bool dontMoveA = A.flags.isFreezeX() || A.flags.isFreezeY();
+			bool dontMoveB = B.flags.isFreezeX() || B.flags.isFreezeY();
 
 			float massInverseA = 1.f / A.motionState.mass;
 			float massInverseB = 1.f / B.motionState.mass;
 
+			if (dontMoveA) { massInverseA = 0; }
+			if (dontMoveB) { massInverseB = 0; }
+
+			if (dontMoveA == 0 && massInverseB == 0) { return; }
+
 			if (A.motionState.mass == 0 || A.motionState.mass == INFINITY) { massInverseA = 0; }
 			if (B.motionState.mass == 0 || B.motionState.mass == INFINITY) { massInverseB = 0; }
 
@@ -1430,12 +1477,18 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 
 			if (tangentA.x == 0 && tangentA.y == 0) { return; }
 			if (tangentB.x == 0 && tangentB.y == 0) { return; }
+			bool dontRotateA = A.flags.isFreezeRotation();
+			bool dontRotateB = B.flags.isFreezeRotation();
 
 			float inertiaInverseA = 1.f / A.motionState.momentOfInertia;
 			float inertiaInverseB = 1.f / B.motionState.momentOfInertia;
 
 			if (A.motionState.momentOfInertia == 0 || A.motionState.momentOfInertia == INFINITY) { inertiaInverseA = 0; }
 			if (B.motionState.momentOfInertia == 0 || B.motionState.momentOfInertia == INFINITY) { inertiaInverseB = 0; }
+			if (dontRotateA) { inertiaInverseA = 0; }
+			if (dontRotateB) { inertiaInverseB = 0; }
+
+			if (inertiaInverseA == 0 && inertiaInverseB == 0) { return; }
 
 			const float PI = 3.1415926;
 
@@ -1541,8 +1594,8 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 			//A.motionState.velocity -= (aInverseMass)*frictionImpulse;
 			//B.motionState.velocity += (bInverseMass)*frictionImpulse;
 
-			A.motionState.applyImpulseWorldPosition(-frictionImpulse, contactPoint);
-			B.motionState.applyImpulseWorldPosition( frictionImpulse, contactPoint);
+			A.motionState.applyImpulseWorldPosition(-frictionImpulse, contactPoint, A.flags);
+			B.motionState.applyImpulseWorldPosition( frictionImpulse, contactPoint, B.flags);
 
 
 		};
@@ -1598,8 +1651,8 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 			//A.motionState.velocity -= massInverseA * impulse;
 			//B.motionState.velocity += massInverseB * impulse;
 
-			A.motionState.applyImpulseWorldPosition(-impulse, contactPoint);
-			B.motionState.applyImpulseWorldPosition( impulse, contactPoint);
+			A.motionState.applyImpulseWorldPosition(-impulse, contactPoint, A.flags);
+			B.motionState.applyImpulseWorldPosition( impulse, contactPoint, B.flags);
 
 			{
 
@@ -1628,6 +1681,20 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 
 		};
 
+
+		//gravity
+		for (int i = 0; i < bodies.size(); i++)
+		{
+			//no need to check for freeze position on x y because I clear them later anyway.
+			if (bodies[i].motionState.mass != 0 && bodies[i].motionState.mass != INFINITY
+				&& !bodies[i].flags.isFreezePosition()
+				)
+			{
+				bodies[i].motionState.acceleration += simulationphysicsSettings.gravity
+					* bodies[i].gravityScale;
+			}
+		}
+
 		size_t bodiesSize = bodies.size();
 		for (int i = 0; i < bodiesSize; i++)
 		{
@@ -1636,8 +1703,8 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 				bodies[i].motionState.mass = INFINITY;
 			}
 
-			applyDrag(bodies[i].motionState);
-			applyAngularDrag(bodies[i].motionState);
+			applyDrag(bodies[i].motionState, bodies[i].dragScale, simulationphysicsSettings);
+			applyAngularDrag(bodies[i].motionState, bodies[i].angularDragScale, simulationphysicsSettings);
 		};
 
 		for (int _ = 0; _ < collisionChecksCount; _++)
@@ -1724,10 +1791,10 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 
 		}
 		
-
 		for (int i = 0; i < bodiesSize; i++)
 		{
-			integrateForces(bodies[i].motionState, deltaTime);
+			integrateForces(bodies[i].motionState, deltaTime, simulationphysicsSettings, 
+				bodies[i].flags);
 			bodies[i].motionState.lastPos = bodies[i].motionState.pos;
 		};
 	
@@ -1741,6 +1808,7 @@ void ph2d::PhysicsEngine::addBody(glm::vec2 centerPos, Collider collider)
 {
 
 	Body body;
+	body.id = ++idCounter;
 	body.motionState.setPos(centerPos);
 	body.collider = collider;
 	body.motionState.mass = collider.computeMass();
@@ -1777,6 +1845,7 @@ glm::vec2 ph2d::rotationToVector(float rotation)
 void ph2d::PhysicsEngine::addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal)
 {
 	Body body;
+	body.id = ++idCounter;
 	body.motionState.setPos(position);
 	body.collider.type = ColliderType::ColliderHalfSpace;
 	body.motionState.mass = 0;
@@ -1788,6 +1857,16 @@ void ph2d::PhysicsEngine::addHalfSpaceStaticObject(glm::vec2 position, glm::vec2
 }
 
 
+void ph2d::Body::applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector)
+{
+	motionState.applyImpulseObjectPosition(impulse, contactVector, flags);
+}
+
+void ph2d::Body::applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos)
+{
+	motionState.applyImpulseWorldPosition(impulse, contactVectorWorldPos, flags);
+}
+
 ph2d::AABB ph2d::Body::getAABB()
 {