Browse Source

stable ph2d push

vlod 1 year ago
parent
commit
a22270dbb2

+ 4 - 3
Pika/CMakeLists.txt

@@ -40,6 +40,7 @@ add_subdirectory(thirdparty/safeSafe)
 add_subdirectory(thirdparty/profilerLib)
 add_subdirectory(thirdparty/box2d-2.4.1)
 add_subdirectory(thirdparty/sushi)
+add_subdirectory(thirdparty/ph2d)
 
 #Define some macros for the project sources
 file(GLOB_RECURSE PIKA_SOURCES_CORE_CONFIG			CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/core/coreConfig/*.cpp")
@@ -82,7 +83,7 @@ target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/pik
 target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/pikaSTD/")
 target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/sharedRuntime/")
 target_link_libraries(pikaCore PRIVATE glad glfw gl2d  gl3d glui
-	glm stb_image stb_truetype imgui safeSave profilerLib sushi)
+	glm stb_image stb_truetype imgui safeSave profilerLib sushi ph2d)
 #################^^^^^^^^#############################
 
 
@@ -99,7 +100,7 @@ target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/game
 target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/sharedRuntime/")
 target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pluggins/")
 target_link_libraries(pikaGameplay PRIVATE glad glfw gl2d gl3d glui glm stb_image 
-	stb_truetype imgui safeSave profilerLib box2d sushi)
+	stb_truetype imgui safeSave profilerLib box2d sushi ph2d)
 #################^^^^^^^^^^^^^^############################
 
 
@@ -123,7 +124,7 @@ target_link_libraries(pikaGameplay PRIVATE glad glfw gl2d gl3d glui glm stb_imag
 #target_include_directories(pikaProduction PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pluggins/")
 #
 #target_link_libraries(pikaProduction PRIVATE glad glfw gl2d gl3d glui glm stb_image 
-#	stb_truetype imgui safeSave profilerLib box2d sushi)
+#	stb_truetype imgui safeSave profilerLib box2d sushi ph2d)
 #
 
 

+ 3 - 1
Pika/core/sharedRuntime/pikaImgui/pikaImgui.cpp

@@ -49,6 +49,7 @@ void pika::pikaImgui::initImgui(PikaContext &pikaContext)
 	io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;         // Enable Multi-Viewport / Platform Windows
 	//io.ConfigViewportsNoAutoMerge = true;
 	//io.ConfigViewportsNoTaskBarIcon = true;
+	io.FontGlobalScale = 2;
 
 	ImGuiStyle &style = ::ImGui::GetStyle();
 	if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@@ -92,7 +93,8 @@ void pika::pikaImgui::initImgui(PikaContext &pikaContext)
 		builder.AddChar(0xf114);//ICON_FK_FOLDER_O
 		builder.BuildRanges(&ranges);
 
-		io.Fonts->AddFontFromFileTTF(PIKA_RESOURCES_PATH "fontawesome-webfont.ttf", 150, 0, ranges.Data);
+		io.Fonts->AddFontFromFileTTF(PIKA_RESOURCES_PATH "fontawesome-webfont.ttf", 
+			150.f/ io.FontGlobalScale, 0, ranges.Data);
 	}
 	io.Fonts->Build();
 

+ 4 - 2
Pika/gameplay/containers.h

@@ -42,13 +42,14 @@ Container *getContainer(const char* name, pika::memory::MemoryArena *memoryArena
 
 #include "containers/bezie/bezie.h"
 
+#include "containers/physicsTest/physicsTest.h"
 
 #if PIKA_PRODUCTION == 1
 
 #define PIKA_ALL_CONTAINERS() \
 	//PIKA_DECLARE_CONTAINER(McDungeonsGameplay) \
 	//PIKA_DECLARE_CONTAINER(McDungeonsMenu) 
-	//PIKA_DECLARE_CONTAINER(Gameplay) 
+	PIKA_DECLARE_CONTAINER(Gameplay) 
 
 #else
 
@@ -67,11 +68,12 @@ Container *getContainer(const char* name, pika::memory::MemoryArena *memoryArena
 	PIKA_DECLARE_CONTAINER(Mario) \
 	PIKA_DECLARE_CONTAINER(Holloknight)\
 	PIKA_DECLARE_CONTAINER(Bezie)\
+	PIKA_DECLARE_CONTAINER(PhysicsTest)\
 	PIKA_DECLARE_CONTAINER(IsometricGame) \
 	PIKA_DECLARE_CONTAINER(MarioEditor) \
 	PIKA_DECLARE_CONTAINER(MarioNeuralTrainer) \
+	PIKA_DECLARE_CONTAINER(McDungeonsGameplay) \
 	PIKA_DECLARE_CONTAINER(MarioNeuralVizualizer) 
-	//PIKA_DECLARE_CONTAINER(McDungeonsGameplay) \
 	//PIKA_DECLARE_CONTAINER(McDungeonsEditor)
 	//PIKA_DECLARE_CONTAINER(McDungeonsMenu)
 

+ 432 - 0
Pika/gameplay/containers/physicsTest/physicsTest.h

@@ -0,0 +1,432 @@
+#pragma once
+
+#include <gl2d/gl2d.h>
+#include <imgui.h>
+#include <baseContainer.h>
+#include <shortcutApi/shortcutApi.h>
+#include <pikaSizes.h>
+#include <imgui_spinner.h>
+#include <ph2d/ph2d.h>
+
+
+struct PhysicsTest: public Container
+{
+
+	gl2d::Renderer2D renderer;
+	ph2d::PhysicsEngine physicsEngine;
+
+	static constexpr float floorPos = 850;
+
+	bool simulate = 1;
+
+	//todo user can request imgui ids; shortcut manager context; allocators
+	static ContainerStaticInfo containerInfo()
+	{
+		ContainerStaticInfo info = {};
+		info.defaultHeapMemorySize = pika::MB(10);
+		info.requestImguiFbo = true;
+		info.pushAnImguiIdForMe = true;
+		info.andInputWithWindowHasFocus = 0;
+		info.andInputWithWindowHasFocusLastFrame = 0;
+
+		return info;
+	}
+
+
+	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
+	{
+		renderer.create(requestedInfo.requestedFBO.fbo);
+	
+		for (int i = 0; i < 1; i++)
+		{
+			//if (i == 1) { mass = 0; }
+
+			if (0)
+			{
+				float w = rand() % 100 + 20;
+				float h = rand() % 100 + 20;
+
+				physicsEngine.addBody({rand() % 800 + 100, rand() % 800 + 100},
+					ph2d::createBoxCollider({w, h}));
+				physicsEngine.bodies.back().motionState.rotation = ((rand() % 800) / 800.f) * 3.14159f;
+			}
+
+			for (int j = 0; j < 2; j++)
+			{
+				float r = rand() % 35 + 10;
+
+				physicsEngine.addBody({rand() % 800 + 100, rand() % 800 + 100},
+					ph2d::createCircleCollider({r}));
+			}
+		}
+
+		//physicsEngine.addBody({500, 1100}, 
+		//	ph2d::createBoxCollider({1100, 10}));
+
+		//physicsEngine.addBody({500, 500}, ph2d::createBoxCollider({300, 300}));
+
+		//physicsEngine.addBody({700, 700}, ph2d::createBoxCollider({300, 300}));
+
+
+		//physicsEngine.addBody({600, 600}, ph2d::createBoxCollider({350, 100}));
+		//physicsEngine.bodies[1].motionState.rotation = glm::radians(30.f);
+
+		physicsEngine.addBody({500, 500}, ph2d::createCircleCollider({55}));
+		//physicsEngine.addBody({800, 100}, ph2d::createCircleCollider({55}));
+		//physicsEngine.addBody({900, 500}, ph2d::createCircleCollider({25}));
+		//physicsEngine.addBody({550, 700}, ph2d::createCircleCollider({25}));
+
+		//std::cout << ph2d::vectorToRotation({0,1}) << "\n";
+		//std::cout << ph2d::vectorToRotation({-1,1}) << "\n";
+		//std::cout << ph2d::vectorToRotation({-1,0}) << "\n";
+		//std::cout << ph2d::vectorToRotation({0,-1}) << "\n";
+		//std::cout << ph2d::vectorToRotation({1,0}) << "\n";
+		//
+		//std::cout << "\n";
+		//std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({0,1}) ).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({0,1}) ).y  << "\n";
+		//std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({-1,1})).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({-1,1})).y << "\n";
+		//std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({-1,0})).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({-1,0})).y << "\n";
+		//std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({0,-1})).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({0,-1})).y << "\n";
+		//std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({1,0}) ).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({1,0}) ).y  << "\n";
+
+		physicsEngine.addHalfSpaceStaticObject({0, floorPos}, {0.1, 1});
+		//physicsEngine.addBody({500, floorPos}, ph2d::createBoxCollider({900, 50}));
+		//physicsEngine.bodies.back().motionState.mass = 0;
+		//physicsEngine.bodies.back().motionState.momentOfInertia = 0;
+
+		return true;
+	}
+
+	bool update(pika::Input input, pika::WindowState windowState,
+		RequestedContainerInfo &requestedInfo)
+	{
+	#pragma region init stuff
+		int w = 0; int h = 0;
+		w = windowState.frameBufferW; //window w
+		h = windowState.frameBufferH; //window h
+
+		glClear(GL_COLOR_BUFFER_BIT); //clear screen
+
+		renderer.updateWindowMetrics(w, h);
+	#pragma endregion
+
+
+		//ph2d::AABB box1 = glm::vec4{300,300, 300,300};
+	//
+	//ph2d::AABB box2 = glm::vec4(glm::vec2(platform::getRelMousePosition()) - glm::vec2(50, 50), 100, 100);
+	//
+	//renderer.renderRectangleOutline(box1.asVec4(), Colors_White);
+	//
+	//auto color = Colors_White;
+	//
+	//if (ph2d::AABBvsAABB(box1, box2))
+	//{
+	//	color = Colors_Red;
+	//}
+	//
+	//renderer.renderRectangleOutline(box2.asVec4(), color);
+
+
+	//ph2d::Circle a = glm::vec3{450,450, 150};
+	//ph2d::Circle b = glm::vec3(glm::vec2(platform::getRelMousePosition()), 50);
+	//renderer.renderCircleOutline(a.center, a.r, Colors_White, 2, 32);
+	//
+	//auto color = Colors_White;
+	//if (ph2d::CirclevsCircle(a, b))
+	//{
+	//	color = Colors_Red;
+	//}
+	//renderer.renderCircleOutline(b.center, b.r, color, 2, 32);
+		static int simulationSpeed = 1;
+		float rightPos = 950;
+
+		//physicsEngine.bodies[0].motionState.rotation = glm::radians(-30.f);
+
+
+		ImGui::PushStyleColor(ImGuiCol_WindowBg, {0.3,0.3,0.3,0.8});
+		ImGui::Begin("Settings");
+
+		ImGui::DragInt("Speed", &simulationSpeed);
+
+		ImGui::SliderAngle("ANgle", &physicsEngine.bodies[0].motionState.rotation);
+
+		ImGui::Checkbox("Simulate", &simulate);
+
+		ImGui::End();
+		ImGui::PopStyleColor();
+
+		static int selected = -1;
+
+		//mouse
+		if (!simulate)
+		{
+			physicsEngine.bodies[0].motionState.setPos({input.mouseX, input.mouseY});
+		}
+
+		static glm::vec2 pressedPosition = {};
+
+		if (input.lMouse.pressed())
+		{
+			selected = -1;
+
+			for (int i = 0; i < physicsEngine.bodies.size(); i++)
+			{
+				if (OBBvsPoint(physicsEngine.bodies[i].getAABB(),
+					physicsEngine.bodies[i].motionState.rotation,
+					{input.mouseX, input.mouseY}))
+				{
+					selected = i;
+					pressedPosition = {input.mouseX, input.mouseY};
+				}
+			}
+		}
+
+		if (selected >= 0)
+		{
+			renderer.renderLine(pressedPosition, {input.mouseX, input.mouseY}, Colors_Blue, 4);
+		}
+
+		if (input.lMouse.released() && selected >= 0)
+		{
+
+			glm::vec2 force = pressedPosition - glm::vec2({input.mouseX, input.mouseY});
+
+			//physicsEngine.bodies[selected].motionState.velocity += force;
+			force *= physicsEngine.bodies[selected].motionState.mass;
+
+			physicsEngine.bodies[selected].motionState.applyImpulseWorldPosition(force,
+				physicsEngine.bodies[selected].motionState.pos
+				//pressedPosition
+			);
+
+			//physicsEngine.bodies[selected].motionState.angularVelocity = 10;
+
+			selected = -1;
+			pressedPosition = {};
+		}
+
+
+		for (int i = 0; i < simulationSpeed; i++)
+		{
+
+			//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)
+			{
+				physicsEngine.collisionChecksCount = 8;
+				physicsEngine.runSimulation(input.deltaTime);
+			}
+			else
+			{
+				physicsEngine.collisionChecksCount = 0;
+				physicsEngine.runSimulation(0);
+			}
+
+			for (auto &b : physicsEngine.bodies)
+			{
+				auto bottom = b.getAABB().max().y;
+				auto left = b.getAABB().min().x;
+				auto right = b.getAABB().max().x;
+				auto top = b.getAABB().min().y;
+
+				//if (bottom > floorPos)
+				//{
+				//	float diff = bottom - floorPos;
+				//	b.motionState.pos.y -= diff;
+				//	b.motionState.lastPos = b.motionState.pos;
+				//
+				//	b.motionState.velocity.y *= -0.9;
+				//}
+
+				if (left < 0)
+				{
+					b.motionState.pos.x -= left;
+					b.motionState.lastPos = b.motionState.pos;
+
+					b.motionState.velocity.x *= -0.9;
+				}
+
+				if (right > rightPos)
+				{
+					b.motionState.pos.x -= right - rightPos;
+					b.motionState.lastPos = b.motionState.pos;
+
+					b.motionState.velocity.x *= -0.9;
+				}
+
+				if (top < 0)
+				{
+					b.motionState.pos.y -= top;
+					b.motionState.lastPos = b.motionState.pos;
+
+					b.motionState.velocity.y *= -0.9;
+				}
+			}
+		}
+
+		//std::cout << physicsEngine.bodies[0].getAABB().max().x << "\n";
+
+		//renderer.renderRectangleOutline({300 - 25, 100 - 25, 50, 50}, Colors_Red);
+		//renderer.renderRectangleOutline({600 - 25, 200 - 25, 50, 50}, Colors_Red);
+
+		float p = 0;
+		glm::vec2 n = {};
+		bool penetrated = 0;
+		glm::vec2 contactPoint = {};
+
+		if (ph2d::BodyvsBody(physicsEngine.bodies[0],
+			physicsEngine.bodies[1],
+			p, n, contactPoint))
+		{
+			penetrated = true;
+		}
+
+		//if (ph2d::OBBvsOBB(physicsEngine.bodies[0].getAABB(),
+		//	physicsEngine.bodies[0].motionState.rotation,
+		//	physicsEngine.bodies[1].getAABB(),
+		//	physicsEngine.bodies[1].motionState.rotation,
+		//	p, n, contactPoint))
+		//{
+		//	penetrated = true;
+		//}
+
+		//auto a = physicsEngine.bodies[0].getAABB();
+		//auto b = physicsEngine.bodies[1].getAABB();
+		//ph2d::Circle a1 = glm::vec3{a.center(),a.size.x / 2};
+		//ph2d::Circle b1 = glm::vec3{b.center(),b.size.x / 2};
+		//if (ph2d::CirclevsCircle(a1, b1, p, n, contactPoint))
+		//{
+		//	penetrated = true;
+		//}
+
+
+		//auto a = physicsEngine.bodies[0].getAABB();
+		//auto b = physicsEngine.bodies[1];
+		//ph2d::LineEquation lineEquation;
+		//lineEquation.createFromRotationAndPoint(b.motionState.rotation,
+		//	b.motionState.pos);
+		//if (ph2d::HalfSpaceVSCircle(lineEquation, a, p, n, contactPoint))
+		//{
+		//	penetrated = true;
+		//}
+
+		//glm::vec2 cornersA[4] = {};
+		//glm::vec2 cornersB[4] = {};
+		//physicsEngine.bodies[0].getAABB().getCornersRotated(cornersA, physicsEngine.bodies[0].motionState.rotation);
+		//physicsEngine.bodies[1].getAABB().getCornersRotated(cornersB, physicsEngine.bodies[1].motionState.rotation);
+		//
+		//float rez = ph2d::calculatePenetrationAlongOneAxe(cornersA, 4, cornersB, 4, {1,0});
+		//if (rez > 0)
+		//{
+		//	penetrated = true;
+		//}
+
+		ImGui::Begin("Settings");
+		ImGui::Text("Penetration: %f", p);
+		ImGui::End();
+
+
+		for (int i = 0; i < physicsEngine.bodies.size(); i++)
+		{
+			auto &b = physicsEngine.bodies[i];
+
+			auto color = Colors_White;
+
+			if (i == selected)
+			{
+				color = Colors_Blue;
+			}
+
+			if (b.intersectPoint({input.mouseX, input.mouseY}))
+			{
+				color = Colors_Turqoise;
+			}
+
+			if (penetrated)
+			{
+				color = Colors_Red;
+			}
+
+			if (b.collider.type == ph2d::ColliderCircle)
+			{
+				renderer.renderCircleOutline(b.motionState.pos,
+					b.collider.collider.circle.radius, color, 2, 32);
+
+				glm::vec2 vector = {1,0};
+				vector = ph2d::rotateAroundCenter(vector, b.motionState.rotation);
+				renderer.renderLine(b.motionState.pos, b.motionState.pos + vector *
+					b.collider.collider.circle.radius, color, 4);
+
+			}
+			else if (b.collider.type == ph2d::ColliderBox)
+			{
+				float rotation = glm::degrees(b.motionState.rotation);
+
+				renderer.renderRectangleOutline(b.getAABB().asVec4(), color, 2, {}, rotation);
+			}
+			else if (b.collider.type == ph2d::ColliderHalfSpace)
+			{
+
+				ph2d::LineEquation lineEquation;
+				lineEquation.createFromRotationAndPoint(b.motionState.rotation,
+					b.motionState.pos);
+
+				glm::vec2 lineEquationStart = lineEquation.getClosestPointToOrigin();
+				lineEquationStart -= lineEquation.getLineVector() * 1000.f;
+				renderer.renderLine(lineEquationStart, lineEquationStart + lineEquation.getLineVector() * 2000.f, Colors_Red);
+
+
+			}
+		}
+
+		//renderer.renderRectangle({-100, floorPos, 100000, 20});
+
+		if (penetrated)
+		{
+			renderer.renderLine(contactPoint,
+				contactPoint + n * 100.f, Colors_Green, 4);
+
+			renderer.renderRectangle({contactPoint - glm::vec2(2,2), 4,4}, Colors_White);
+		}
+
+
+		//glm::vec2 lineEquationStart = lineEquation.getClosestPointToOrigin();
+		//lineEquationStart -= lineEquation.getLineVector() * 1000.f;
+		//renderer.renderLine(lineEquationStart, lineEquationStart + lineEquation.getLineVector() * 2000.f, Colors_Red);
+
+
+		//ph2d::LineEquation lineEquation;
+		//lineEquation.createFromNormalAndPoint({0,1}, {0, floorPos});
+
+		//float pl = 0;
+		//pl = lineEquation.computeEquation(platform::getRelMousePosition());
+		//ImGui::Begin("Settings");
+		//ImGui::Text("Penetration line: %f", pl);
+		//ImGui::End();
+
+
+		//glm::vec2 p2 = platform::getRelMousePosition();
+		//p2 = ph2d::rotateAroundCenter(p2, glm::radians(45.f));
+		//renderer.renderRectangle({p2, 10, 10}, Colors_Red);
+
+
+
+
+		renderer.flush();
+
+		return true;
+	}
+
+	//optional
+	void destruct(RequestedContainerInfo &requestedInfo)
+	{
+
+	}
+
+};

+ 1 - 66
Pika/resources/logs.txt

@@ -1,66 +1 @@
-#2024-06-10 13:05:12: Created container: MarioNeuralTrainer
-#2024-06-10 13:07:51: Destroyed continer: MarioNeuralTrainer #1
-#2024-06-10 13:09:13[warning]: Couldn't reloaded dll
-#2024-06-10 13:09:14: Reloaded dll
-#2024-06-10 13:09:21: Created container: MarioNeuralTrainer
-#2024-06-10 13:11:16: Destroyed continer: MarioNeuralTrainer #2
-#2024-06-10 13:11:41[warning]: Couldn't reloaded dll
-#2024-06-10 13:11:41: Reloaded dll
-#2024-06-10 13:12:17[warning]: Couldn't reloaded dll
-#2024-06-10 13:12:17: Reloaded dll
-#2024-06-10 13:12:29: Created container: MarioNeuralTrainer
-#2024-06-10 14:16:11: Destroyed continer: MarioNeuralTrainer #3
-#2024-06-10 14:18:09: Created container: MarioNeuralVizualizer
-#2024-06-10 14:18:11: Destroyed continer: MarioNeuralVizualizer #4
-#2024-06-10 14:18:18: Created container: MarioNeuralVizualizer
-#2024-06-10 14:18:45: Destroyed continer: MarioNeuralVizualizer #5
-#2024-06-10 14:18:47: Created container: MarioEditor
-#2024-06-10 14:18:50: Destroyed continer: MarioEditor #6
-#2024-06-10 14:18:52: Created container: MarioEditor
-#2024-06-10 14:19:16: Destroyed continer: MarioEditor #7
-#2024-06-10 14:19:20: Created container: MarioNeuralVizualizer
-#2024-06-10 14:19:59: Destroyed continer: MarioNeuralVizualizer #8
-#2024-06-10 14:20:02: Created container: MarioNeuralVizualizer
-#2024-06-10 14:20:25: Destroyed continer: MarioNeuralVizualizer #9
-#2024-06-10 14:20:28: Created container: MarioNeuralVizualizer
-#2024-06-10 14:21:03: Destroyed continer: MarioNeuralVizualizer #10
-#2024-06-10 14:21:07: Created container: MarioEditor
-#2024-06-10 14:21:51: Destroyed continer: MarioEditor #11
-#2024-06-10 14:21:53: Created container: MarioNeuralVizualizer
-#2024-06-10 14:22:33: Destroyed continer: MarioNeuralVizualizer #12
-#2024-06-10 14:22:38: Created container: MarioEditor
-#2024-06-10 14:22:57: Destroyed continer: MarioEditor #13
-#2024-06-10 14:23:00: Created container: MarioNeuralTrainer
-#2024-06-10 14:23:02: Destroyed continer: MarioNeuralTrainer #14
-#2024-06-10 14:23:03: Created container: MarioNeuralVizualizer
-#2024-06-10 14:23:18: Destroyed continer: MarioNeuralVizualizer #15
-#2024-06-10 14:23:20: Created container: MarioEditor
-#2024-06-10 14:23:33: Destroyed continer: MarioEditor #16
-#2024-06-10 14:23:35: Created container: MarioNeuralVizualizer
-#2024-06-10 14:24:12: Destroyed continer: MarioNeuralVizualizer #17
-#2024-06-10 14:24:15: Created container: MarioEditor
-#2024-06-10 14:25:00: Destroyed continer: MarioEditor #18
-#2024-06-10 14:25:04: Created container: MarioNeuralVizualizer
-#2024-06-10 14:25:17: Destroyed continer: MarioNeuralVizualizer #19
-#2024-06-10 14:25:22: Created container: MarioEditor
-#2024-06-10 14:25:48: Destroyed continer: MarioEditor #20
-#2024-06-10 14:25:50: Created container: MarioNeuralVizualizer
-#2024-06-10 14:26:26: Destroyed continer: MarioNeuralVizualizer #21
-#2024-06-10 14:26:29: Created container: MarioNeuralVizualizer
-#2024-06-10 14:26:52: Destroyed continer: MarioNeuralVizualizer #22
-#2024-06-10 14:26:54: Created container: MarioEditor
-#2024-06-10 14:27:08: Destroyed continer: MarioEditor #23
-#2024-06-10 14:27:12: Created container: MarioNeuralVizualizer
-#2024-06-10 14:27:31: Destroyed continer: MarioNeuralVizualizer #24
-#2024-06-10 14:27:34: Created container: MarioEditor
-#2024-06-10 14:27:49: Destroyed continer: MarioEditor #25
-#2024-06-10 14:27:51: Created container: MarioNeuralVizualizer
-#2024-06-10 14:28:07: Destroyed continer: MarioNeuralVizualizer #26
-#2024-06-10 14:28:44: Created container: MarioEditor
-#2024-06-10 14:29:25: Destroyed continer: MarioEditor #27
-#2024-06-10 14:29:28: Created container: MarioNeuralTrainer
-#2024-06-10 14:34:03[warning]: Couldn't reloaded dll
-#2024-06-10 14:34:03: Reloaded dll
-#2024-06-10 15:21:39: Created container: MarioNeuralVizualizer
-#2024-06-10 15:22:23: Destroyed continer: MarioNeuralVizualizer #29
-#2024-06-10 15:22:26: Destroyed continer: MarioNeuralTrainer #28
+#2024-11-21 12:45:52: Created container: PhysicsTest

+ 0 - 206
Pika/resources/mario/13final3.txt

@@ -1,206 +0,0 @@
--6 0.93 1
-1 1.01837 16.25
--7 5.51926 142.25
--7 15.5731 142.198
--7 22.3413 142.25
--6 41.8178 142.225
--7 92.4541 143.119
--6.32762 65.2607 142.234
--6 73.1387 142.25
-15.25 109.207 142.25
--6 66.0348 142.163
--7 46.9409 142.115
--7 98.9143 142.247
--7 66.8713 142.23
--7 72.936 172.712
--6 68.9017 142.25
--7 101.025 142.25
--7 86.5376 142.24
-15.25 97.0568 142.25
-15.055 63.426 142.25
-15.1236 104.678 213.408
-15.0753 88.0944 171.685
--7 51.9047 142.25
-15.2152 109.652 142.25
--80.9007 89.335 142.25
--100.75 9.61952 70.0827
--95.8333 46.7004 70.25
--95.8521 49.9255 75.2058
--100.934 48.1698 75.25
--100.757 37.5398 70.25
--95.9361 52.2058 70.25
-11.25 38.0538 70.25
-11.1299 56.0759 70.25
-11.25 61.3732 72.0643
-11.1609 51.35 70.25
-11.0737 45.2752 70.2421
-11.0529 50.1128 70.1788
-11.2234 53.5343 70.25
-11.1292 47.8133 70.25
-11.1141 56.592 70.25
-11.1176 47.0046 70.25
-11.25 39.24 70.25
-11.0943 52.5134 70.25
-11.0539 44.1253 70.2419
-11.0987 57.172 72.25
-11.0715 43.1225 70.2101
-11.068 45.485 70.25
-11.25 48.6614 70.2059
-11.1939 47.8139 70.25
-11.0689 51.5021 70.1575
-11.0952 47.6442 70.25
-11.1862 56.0921 70.25
-11.25 64.961 70.25
-11.25 53.3155 70.25
-11.1246 42.3332 70.25
-11.1262 49.0376 70.25
-11.161 32.1356 70.25
-11.1258 51.1665 70.2142
-11.2082 48.8226 70.25
-11.0552 46.026 70.1634
-11.164 55.5797 70.25
-11.1988 50.4543 70.25
-11.1717 40.7197 70.25
-11.25 53.0774 70.25
-11.1407 48.6169 70.25
-11.1111 49.2111 70.25
-11.1619 39.0458 70.25
-11.1272 43.1044 70.25
-11.1571 52.7147 70.25
-11.2229 48.0598 70.25
-11.2426 51.0657 70.25
-11.0686 49.7177 70.25
-11.1306 47.0687 72.2183
-11.1324 41.6338 70.25
-11.25 46.813 70.1907
-11.1769 55.8654 70.25
-11.0598 24.0653 70.1452
-11.1533 46.2564 70.1781
-11.0734 46.6965 70.25
-11.062 58.9164 70.25
-11.0793 49.0658 70.25
-11.11 45.8175 70.1991
-11.1981 45.2535 70.25
-11.0753 56.4375 85.6745
-11.2026 44.321 70.25
-11.0759 65.6535 85.8571
-11.2232 37.9387 70.25
-11.25 51.7602 70.25
-11.0755 52.4644 70.25
-11.0563 42.009 70.2107
-11.1821 42.5855 70.1703
-11.2069 46.7493 70.25
-11.2034 32.696 75.25
-11.0546 44.9425 100.988
-11.25 28.9211 80.6197
--100.822 37.2389 70.25
-11.1014 32.5578 70.25
--39 43.5033 80.9077
--39 40.854 101.169
--100.819 17.2662 70.2378
-11.1728 41.0344 70.1735
-11.25 39.086 70.25
-11.1932 49.2759 111.419
-11.0954 42.8222 75.25
--39 45.8748 70.25
--39 36.7886 70.25
--39 45.0181 70.25
--39 46.3211 70.2238
--34 44.4911 75.2446
--95.811 36.0113 70.25
--43.3689 27.5641 70.25
--110.75 55.8536 80.7881
--24.8629 49.3729 80.8336
--110.934 52.8551 75.25
--100.865 29.7434 70.25
--120.899 16.0349 70.2417
--95.8968 44.1059 96.4613
--100.75 45.4629 101.694
--110.889 33.6978 101.68
--107.75 36.4744 96.2874
--110.799 30.0826 96.2543
--105.929 36.1073 101.404
--100.9 29.9602 113.982
--110.851 33.8543 131.959
--105.83 42.6677 137.357
--107.75 23.84 104.648
--115.75 18.6566 104.41
--110.848 14.5821 109.009
--115.846 16.1177 109.41
--110.75 34.9513 111.573
--100.75 57.0261 137.127
--110.927 22.7531 136.241
--115.75 54.2952 137.11
--120.765 14.2254 141.734
--120.832 53.1496 131.266
--110.935 32.3862 137.068
--110.949 17.4774 149.574
--110.877 45.4863 111.586
--100.926 25.3036 142.226
--100.838 35.3961 154.665
--115.75 13.9035 149.111
--100.922 52.9921 154.378
--95.8005 52.6826 149.483
--110.75 32.8232 109.363
--110.75 32.466 142.309
--105.75 64.6865 109.262
--100.947 25.287 104.442
--105.948 55.2733 154.293
--100.948 45.8765 154.445
--100.918 37.3492 107.683
--100.75 36.619 111.115
--97.7623 40.7841 114.21
--100.84 64.4317 154.475
--112.75 32.0748 104.523
--90.8808 -43.4721 104.383
--110.861 36.9301 154.191
--100.829 34.4607 109.483
--92.9276 41.2109 109.322
--115.75 59.1121 154.59
--100.761 63.2064 142.413
--105.757 38.8673 109.474
--110.863 35.8856 136.989
--105.823 60.9319 111.313
--105.914 58.4272 111.69
--95.75 50.3066 159.277
--105.928 28.9297 154.362
--100.917 55.0227 154.73
--90.9491 34.4204 111.74
--100.887 77.4304 159.304
--95.8688 42.0334 164.331
--100.919 57.1156 154.343
--110.765 46.3189 147.367
--100.75 26.5976 142.493
--95.9264 26.9607 159.591
--95.9184 12.7885 111.885
--90.8284 41.863 111.764
--100.848 28.6903 159.359
--100.945 47.4481 111.997
--100.92 54.4523 159.201
--95.8967 56.2565 154.53
--105.829 23.7954 154.558
--100.83 13.6679 114.498
--95.9479 52.5136 109.297
--95.888 31.653 109.082
--90.75 47.9073 112.427
--100.792 41.2214 147.287
--100.939 43.863 159.267
--90.9155 47.3439 154.234
--90.75 58.7311 154.254
--100.775 63.0603 159.789
--95.7874 54.3981 111.779
--95.75 61.918 154.37
-11.1432 28.6187 159.275
--95.909 63.2573 159.251
--95.75 48.6257 111.755
--90.75 53.9431 159.315
--90.75 38.8905 159.243
--95.9362 59.2374 159.429
--100.75 47.3251 114.363
--100.83 48.5408 159.236
--100.75 46.6687 111.583
--95.8879 49.6231 157.003
--95.7626 54.1305 153.969
--90.75 45.9726 107.246
--95.75 37.2693 159.261
--90.75 36.1235 111.885

BIN
Pika/resources/mario/test2.mario


BIN
Pika/resources/mario/test4.mario


+ 112 - 42
Pika/thirdparty/gl2d/include/gl2d/gl2d.h

@@ -1,6 +1,6 @@
 //////////////////////////////////////////////////
-//gl2d.h				1.5.0
-//Copyright(c) 2020 Luta Vlad
+//gl2d.h				1.6.1
+//Copyright(c) 2020 - 2024 Luta Vlad
 //https://github.com/meemknight/gl2d
 //
 //	dependences: glew(or any loader you want to use), glm, stb_image, stb_trueType
@@ -11,7 +11,7 @@
 //		texture transparency
 //	draw text with font and shadows
 //	camera
-//	shaders
+//	custom shaders + post processing effects!
 //	setVsync
 //	texture atlases and loading textures with \
 //		padding to fix visual bugs when using \
@@ -19,6 +19,7 @@
 //	draw to screen of frame buffer that	can \
 //		be used as a texture
 //
+// 
 //	a particle system that can use a custom \
 //	shader and apply a pixelate effect
 //
@@ -40,12 +41,14 @@
 //if this is true it will use opengl130. If not it will use fome functionality from opengl3.
 #define GL2D_USE_OPENGL_130 false
 
+//this is how the library should load textures by default.
 #define GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED false
 #define GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS true
 
 
-//version of the shading language. this is the minimum but you can go lower if you modify the shader code with minimal effort
-#define GL2D_OPNEGL_SHADER_VERSION "#version 130"
+//version of the shading language.
+//#version 130 is minimum, #version 330 is right now so it can run on MacOS
+#define GL2D_OPNEGL_SHADER_VERSION "#version 330"
 #define GL2D_OPNEGL_SHADER_PRECISION "precision highp float;"
 
 //this is the default capacity of the renderer
@@ -65,10 +68,10 @@ namespace gl2d
 	void init();
 
 	//Deinitializes the library.
-	void clearnup();
+	void cleanup();
 
 	//The default error function, it writes to the console.
-	void defaultErrorFunc(const char* msg, void *userDefinedData);
+	void defaultErrorFunc(const char *msg, void *userDefinedData);
 
 	//set by the user, it is passed to the error function
 	void setUserDefinedData(void *data);
@@ -76,21 +79,41 @@ namespace gl2d
 	using errorFuncType = decltype(defaultErrorFunc);
 
 	//for the user to set a custom error function
-	errorFuncType* setErrorFuncCallback(errorFuncType* newFunc);
+	errorFuncType *setErrorFuncCallback(errorFuncType *newFunc);
 
 	struct Font;
 
 	//returns false on fail
 	bool setVsync(bool b);
 
+	///////////////////// SHADERS ///////////////////
+#pragma region shaders
+
 	struct ShaderProgram
 	{
-		GLuint id;
-		int u_sampler;
+		GLuint id = 0;
+		int u_sampler = 0;
+
+		void bind() { glUseProgram(id); };
+
+		void clear() { glDeleteProgram(id); *this = {}; }
 	};
 
 	ShaderProgram createShaderProgram(const char *vertex, const char *fragment);
 
+	ShaderProgram createShaderFromFile(const char *filePath);
+
+	ShaderProgram createShader(const char *fragment);
+
+	//the only diufference between a normal shader and a post process shader,
+	//is that that post process loads a vertex shader that doesn't acces color or texture uv,
+	//it just renders to the entire screen, and passes the texture position to the fragment.
+	ShaderProgram createPostProcessShaderFromFile(const char *filePath);
+
+	ShaderProgram createPostProcessShader(const char *fragment);
+
+#pragma endregion
+
 	struct Camera;
 
 	namespace internal
@@ -140,40 +163,60 @@ namespace gl2d
 		GLuint id = 0;
 
 		Texture() {};
-		explicit Texture(const char* file, bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED,
+		explicit Texture(const char *file, bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED,
 			bool useMipMaps = GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS)
-			{ loadFromFile(file, pixelated, useMipMaps); }
+		{
+			loadFromFile(file, pixelated, useMipMaps);
+		}
 
+		//returns the texture dimensions
 		glm::ivec2 GetSize();
 
 		//Note: This function expects a buffer of bytes in GL_RGBA format
-		void createFromBuffer(const char* image_data, const int width,
+		void createFromBuffer(const char *image_data, const int width,
 			const int height, bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED, bool useMipMaps = GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS);
-		
+
 		//used internally. It creates a 1by1 white texture
-		void create1PxSquare(const char* b = 0);
-		
-		void createFromFileData(const unsigned char* image_file_data, const size_t image_file_size, 
+		void create1PxSquare(const char *b = 0);
+
+		void createFromFileData(const unsigned char *image_file_data, const size_t image_file_size,
 			bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED, bool useMipMaps = GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS);
 
 		//For texture atlases.
 		//Adds a pixel padding between sprites elements to avoid some visual bugs.
 		//Block size is the size of a block in pixels.
 		//To be used with texture atlas padding to get the texture coordonates.
-		void createFromFileDataWithPixelPadding(const unsigned char* image_file_data,
+		void createFromFileDataWithPixelPadding(const unsigned char *image_file_data,
 			const size_t image_file_size, int blockSize,
 			bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED, bool useMipMaps = GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS);
 
-		void loadFromFile(const char* fileName,
+		void loadFromFile(const char *fileName,
 			bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED, bool useMipMaps = GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS);
 
 		//For texture atlases.
 		//Adds a pixel padding between sprites elements to avoid some visual bugs.
 		//Block size is the size of a block in pixels.
 		//To be used with texture atlas padding to get the texture coordonates.
-		void loadFromFileWithPixelPadding(const char* fileName, int blockSize,
+		void loadFromFileWithPixelPadding(const char *fileName, int blockSize,
 			bool pixelated = GL2D_DEFAULT_TEXTURE_LOAD_MODE_PIXELATED, bool useMipMaps = GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS);
 
+
+		//returns how much memory does the texture take (bytes),
+		//used for allocating your buffer when using readTextureData
+		//you can also optionally get the width and the height of the texture using outSize
+		size_t getMemorySize(int mipLevel = 0, glm::ivec2 *outSize = 0);
+
+		//reads the texture data back into RAM, you need to specify
+		//the buffer to read into yourself, allocate it using
+		//getMemorySize to know the size in bytes.
+		//The data will be in RGBA format, one byte each component
+		void readTextureData(void *buffer, int mipLevel = 0);
+
+		//reads the texture data back into RAM
+		//The data will be in RGBA format, one byte each component
+		//You can also optionally get the width and the height of the texture using outSize
+		std::vector<unsigned char> readTextureData(int mipLevel = 0, glm::ivec2 *outSize = 0);
+
 		void bind(const unsigned int sample = 0);
 		void unbind();
 
@@ -194,7 +237,7 @@ namespace gl2d
 	struct TextureAtlas
 	{
 		TextureAtlas() {};
-		TextureAtlas(int x, int y) :xCount(x), yCount(y) {};
+		TextureAtlas(int x, int y):xCount(x), yCount(y) {};
 
 		int xCount = 0;
 		int yCount = 0;
@@ -212,7 +255,7 @@ namespace gl2d
 		TextureAtlasPadding() {};
 
 		//count count size of the full texture(in pixels)
-		TextureAtlasPadding(int x, int y, int xSize, int ySize) :xCount(x), yCount(y)
+		TextureAtlasPadding(int x, int y, int xSize, int ySize):xCount(x), yCount(y)
 			, xSize(xSize), ySize(ySize)
 		{
 		};
@@ -249,6 +292,7 @@ namespace gl2d
 		void createFromTTF(const unsigned char *ttf_data, const size_t ttf_data_size);
 		void createFromFile(const char *file);
 
+		void cleanup();
 	};
 
 
@@ -267,7 +311,7 @@ namespace gl2d
 	struct Camera
 	{
 		glm::vec2  position = {};
-	
+
 		// Camera rotation in degrees
 		float rotation = 0.f;
 
@@ -302,6 +346,9 @@ namespace gl2d
 	//using the texture member.
 	struct FrameBuffer
 	{
+		FrameBuffer() {};
+		explicit FrameBuffer(unsigned int w, unsigned int h) { create(w, h); };
+
 		unsigned int fbo = 0;
 		Texture texture = {};
 
@@ -325,7 +372,6 @@ namespace gl2d
 		bufferSize
 	};
 
-	typedef struct Renderer2D Renderer2D;
 	struct Renderer2D
 	{
 		Renderer2D() {};
@@ -357,7 +403,7 @@ namespace gl2d
 		std::vector<glm::vec4>spriteColors;
 		std::vector<glm::vec2>texturePositions;
 		std::vector<Texture>spriteTextures;
-		
+
 		//glm::vec2 spritePositions[GL2D_Renderer2D_Max_Triangle_Capacity * 6];
 		//glm::vec4 spriteColors[GL2D_Renderer2D_Max_Triangle_Capacity * 6];
 		//glm::vec2 texturePositions[GL2D_Renderer2D_Max_Triangle_Capacity * 6];
@@ -382,12 +428,12 @@ namespace gl2d
 
 
 		//window metrics, should be up to date at all times
-		int windowW = 0;
-		int windowH = 0;
+		int windowW = -1;
+		int windowH = -1;
 		void updateWindowMetrics(int w, int h) { windowW = w; windowH = h; }
 
 		//converts pixels to screen (top left) (bottom right)
-		glm::vec4 toScreen(const glm::vec4& transform);
+		glm::vec4 toScreen(const glm::vec4 &transform);
 
 		//clears the things that are to be drawn when calling flush
 		inline void clearDrawData()
@@ -413,12 +459,12 @@ namespace gl2d
 			const float spacing = 4, const float line_space = 3, bool showInCenter = 1, const Color4f ShadowColor = {0.1,0.1,0.1,1}
 		, const Color4f LightColor = {});
 
-		//determins the text size so that it fits in the given box,
+		//determines the text size so that it fits in the given box,
 		//the x and y components of the transform are ignored
 		float determineTextRescaleFitSmaller(const std::string &str,
 			gl2d::Font &f, glm::vec4 transform, float maxSize);
 
-		//determins the text size so that it fits in the given box,
+		//determines the text size so that it fits in the given box,
 		//the x and y components of the transform are ignored
 		float determineTextRescaleFit(const std::string &str,
 			gl2d::Font &f, glm::vec4 transform);
@@ -439,7 +485,7 @@ namespace gl2d
 		glm::vec2 getTextSizeWrapped(const std::string &text,
 			gl2d::Font f, float maxTextLenght, float baseSize, float spacing = 4, float lineSpacing = 3);
 
-		//determins the text size so that it fits in the given box,
+		//determines the text size so that it fits in the given box,
 		//the x and y components of the transform are ignored
 		float determineTextRescaleFitBigger(const std::string &str,
 			gl2d::Font &f, glm::vec4 transform, float minSize);
@@ -447,7 +493,7 @@ namespace gl2d
 		void renderRectangle(const Rect transforms, const Texture texture, const Color4f colors[4], const glm::vec2 origin = {}, const float rotationDegrees = 0.f, const glm::vec4 textureCoords = GL2D_DefaultTextureCoords);
 		inline void renderRectangle(const Rect transforms, const Texture texture, const Color4f colors = {1,1,1,1}, const glm::vec2 origin = {}, const float rotationDegrees = 0, const glm::vec4 textureCoords = GL2D_DefaultTextureCoords)
 		{
-			Color4f c[4] = { colors,colors,colors,colors };
+			Color4f c[4] = {colors,colors,colors,colors};
 			renderRectangle(transforms, texture, c, origin, rotationDegrees, textureCoords);
 		}
 
@@ -455,22 +501,22 @@ namespace gl2d
 		void renderRectangleAbsRotation(const Rect transforms, const Texture texture, const Color4f colors[4], const glm::vec2 origin = {}, const float rotationDegrees = 0.f, const glm::vec4 textureCoords = GL2D_DefaultTextureCoords);
 		inline void renderRectangleAbsRotation(const Rect transforms, const Texture texture, const Color4f colors = {1,1,1,1}, const glm::vec2 origin = {}, const float rotationDegrees = 0.f, const glm::vec4 textureCoords = GL2D_DefaultTextureCoords)
 		{
-			Color4f c[4] = { colors,colors,colors,colors };
+			Color4f c[4] = {colors,colors,colors,colors};
 			renderRectangleAbsRotation(transforms, texture, c, origin, rotationDegrees, textureCoords);
 		}
 
-		void renderRectangle(const Rect transforms, const Color4f colors[4], const glm::vec2 origin = { 0,0 }, const float rotationDegrees = 0);
-		inline void renderRectangle(const Rect transforms, const Color4f colors, const glm::vec2 origin = { 0,0 }, const float rotationDegrees = 0)
+		void renderRectangle(const Rect transforms, const Color4f colors[4], const glm::vec2 origin = {0,0}, const float rotationDegrees = 0);
+		inline void renderRectangle(const Rect transforms, const Color4f colors = {1,1,1,1}, const glm::vec2 origin = {0,0}, const float rotationDegrees = 0)
 		{
-			Color4f c[4] = { colors,colors,colors,colors };
+			Color4f c[4] = {colors,colors,colors,colors};
 			renderRectangle(transforms, c, origin, rotationDegrees);
 		}
 
 		//abs rotation means that the rotaion is relative to the screen rather than object
-		void renderRectangleAbsRotation(const Rect transforms, const Color4f colors[4], const glm::vec2 origin = { 0,0 }, const float rotationDegrees = 0);
-		inline void renderRectangleAbsRotation(const Rect transforms, const Color4f colors, const glm::vec2 origin = { 0,0 }, const float rotationDegrees = 0)
+		void renderRectangleAbsRotation(const Rect transforms, const Color4f colors[4], const glm::vec2 origin = {0,0}, const float rotationDegrees = 0);
+		inline void renderRectangleAbsRotation(const Rect transforms, const Color4f colors = {1,1,1,1}, const glm::vec2 origin = {0,0}, const float rotationDegrees = 0)
 		{
-			Color4f c[4] = { colors,colors,colors,colors };
+			Color4f c[4] = {colors,colors,colors,colors};
 			renderRectangleAbsRotation(transforms, c, origin, rotationDegrees);
 		}
 
@@ -479,11 +525,13 @@ namespace gl2d
 		void renderLine(const glm::vec2 start, const glm::vec2 end, const Color4f color, const float width = 2.f);
 
 		void renderRectangleOutline(const glm::vec4 position, const Color4f color, const float width = 2.f, const glm::vec2 origin = {}, const float rotationDegrees = 0);
-		
-		void renderCircleOutline(const glm::vec2 position, const Color4f color, const float size, const float width = 2.f, const unsigned int segments = 16);
 
-		//used for ui. draws a texture that scales the margins different so buttons of different sizes can be drawn.
+		void renderCircleOutline(const glm::vec2 position, const float size, const Color4f color, const float width = 2.f, const unsigned int segments = 16);
+
+		//legacy, use render9Patch2
 		void render9Patch(const Rect position, const int borderSize, const Color4f color, const glm::vec2 origin, const float rotationDegrees, const Texture texture, const Texture_Coords textureCoords, const Texture_Coords inner_texture_coords);
+
+		//used for ui. draws a texture that scales the margins different so buttons of different sizes can be drawn.
 		void render9Patch2(const Rect position, const Color4f color, const glm::vec2 origin, const float rotationDegrees, const Texture texture, const Texture_Coords textureCoords, const Texture_Coords inner_texture_coords);
 
 		void clearScreen(const Color4f color = Color4f{0,0,0,0});
@@ -494,6 +542,9 @@ namespace gl2d
 		//will reset on the current stack
 		void resetCameraAndShader();
 
+		//The framebuffer need to have the same size as the input!
+		void renderPostProcess(ShaderProgram shader, Texture input, FrameBuffer result = {});
+
 		//Only when this function is called it draws to the screen the things rendered.
 		//If clearDrawData is false, the rendering information will be kept.
 		//Usefull if you want to render something twice or render again on top for some reason
@@ -502,6 +553,25 @@ namespace gl2d
 		//Renders to a fbo instead of the screen. The fbo is just a texture.
 		//If clearDrawData is false, the rendering information will be kept.
 		void flushFBO(FrameBuffer frameBuffer, bool clearDrawData = true);
+
+		void renderFrameBufferToTheEntireScreen(gl2d::FrameBuffer fbo, gl2d::FrameBuffer screen = {});
+
+		void renderTextureToTheEntireScreen(gl2d::Texture t, gl2d::FrameBuffer screen = {});
+
+		gl2d::FrameBuffer postProcessFbo1 = {};
+		gl2d::FrameBuffer postProcessFbo2 = {};
+
+		//internal use
+		bool internalPostProcessFlip = 0;
+
+		//the FBO size should be equal to the current configured w and h of the renderer
+		void flushPostProcess(const std::vector<ShaderProgram> &postProcesses,
+			FrameBuffer frameBuffer = {}, bool clearDrawData = true);
+
+		//the FBO size should be equal to the current configured w and h of the renderer
+		void postProcessOverATexture(const std::vector<ShaderProgram> &postProcesses,
+			gl2d::Texture in,
+			FrameBuffer frameBuffer = {});
 	};
 
 	void enableNecessaryGLFeatures();

File diff suppressed because it is too large
+ 422 - 101
Pika/thirdparty/gl2d/src/gl2d.cpp


+ 7 - 0
Pika/thirdparty/ph2d/CMakeLists.txt

@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.1)
+project(ph2d)
+
+add_library(ph2d)
+target_sources(ph2d PRIVATE "src/ph2d.cpp")
+target_include_directories(ph2d PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_link_libraries(ph2d PUBLIC glm)

+ 280 - 0
Pika/thirdparty/ph2d/include/ph2d/ph2d.h

@@ -0,0 +1,280 @@
+//////////////////////////////////////////////////
+//ph2d.h				0.0.1
+//Copyright(c) 2024 Luta Vlad - Low Level Game Dev
+// please credit me if you want, 
+// and keep this in the code
+//
+//	dependences: glm
+//
+//////////////////////////////////////////////////
+
+//Library conventions
+
+//for positions and size we use vec4 or AABB. But the idea is, whenever I use a vec4,
+// that means position x, position y; size x, size y.
+// you can easily convert from a vec4 to an aabb and back
+
+#undef min
+#undef max
+
+#include <glm/glm.hpp>
+#include <vector>
+
+namespace ph2d
+{
+	struct LineEquation;
+
+
+	glm::vec2 rotationToVector(float rotation);
+
+	float vectorToRotation(const glm::vec2 &vector);
+
+	struct AABB
+	{
+		AABB() {};
+
+		AABB(glm::vec4 a): pos(a.x, a.y), size(a.z, a.w) {};
+
+		glm::vec2 pos = {};
+		glm::vec2 size = {};
+
+		glm::vec4 asVec4() { return glm::vec4{pos, size}; }
+
+		glm::vec2 min() { return pos; }
+		glm::vec2 max() { return pos + size; }
+		glm::vec2 center() { return pos + size / 2.f; }
+
+		void getMinMaxPointsRotated(glm::vec2 &outMin, glm::vec2 &outMax, float r);
+
+		void getCornersRotated(glm::vec2 corners[4], float r);
+
+
+		void rotateAroundCenter(float r);
+
+		float down() { return pos.y + size.y; }
+		float top() { return pos.y; }
+		float left() { return pos.x; }
+		float right() { return pos.x + size.x; }
+	};
+
+	//todo remove?
+	struct Circle
+	{
+		Circle() {};
+
+		Circle(glm::vec3 a): center(a.x, a.y), r(a.z) {};
+
+		glm::vec2 center = {};
+		float r = 0;
+
+		glm::vec2 getTopLeftCorner() { return center += glm::vec2(-r, r); }
+
+		AABB getAABB() { return glm::vec4(getTopLeftCorner(), r*2, r*2); }
+	};
+
+	bool OBBvsOBB(AABB a, float ar, AABB b, float br);
+
+	bool OBBvsOBB(AABB a, float ar, AABB b, float br, float &penetration, 
+		glm::vec2 &normal, glm::vec2 &contactPoint);
+
+	bool AABBvsAABB(AABB a, AABB b, float delta = 0);
+
+	bool AABBvsPoint(AABB a, glm::vec2 b, float delta = 0);
+
+	bool OBBvsPoint(AABB a, float rotation, glm::vec2 b, float delta = 0);
+
+	bool CircleVsPoint(glm::vec2 pos, float r, glm::vec2 p, float delta = 0);
+
+	bool HalfSpaceVSCircle(LineEquation line, AABB circle, float &penetration, glm::vec2 &normal, glm::vec2 &contactPoint);
+
+	bool OBBvsCircle(AABB abox, float ar, AABB bbox, float &penetration, glm::vec2 &normal, 
+		glm::vec2 &contactPoint);
+
+	bool CirclevsCircle(Circle a, Circle b,
+		float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint);
+
+	float calculatePenetrationAlongOneAxe(glm::vec2 *aPoints, size_t aPointsCount,
+		glm::vec2 *bPoints, size_t bPointsCount, glm::vec2 axeDirection, bool *flipSign = 0);
+
+	glm::vec2 rotateAroundCenter(glm::vec2 in, float r);
+
+	glm::vec2 rotateAroundPoint(glm::vec2 in, glm::vec2 centerReff, float r);
+
+	struct MotionState
+	{
+		glm::vec2 pos = {};
+		glm::vec2 lastPos = {};
+		glm::vec2 velocity = {};
+		glm::vec2 acceleration = {};
+
+		float rotation = 0; // radians
+		float angularVelocity = 0;
+		float torque = 0;
+		float mass = 1;
+		float momentOfInertia = 1;
+
+		void setPos(glm::vec2 p) { pos = p; lastPos = p; }
+
+		void applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector);
+		
+		void applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos);
+
+	};
+
+	struct LineEquation
+	{
+		LineEquation() {};
+
+		glm::vec3 lineEquation = {};
+
+		glm::vec2 getNormal() const
+		{
+			return glm::vec2(lineEquation.x, lineEquation.y);
+		}
+
+		void normalize()
+		{
+			glm::vec2 n = glm::vec2(lineEquation.x, lineEquation.y);
+			float l = glm::length(n);
+
+			if (l <= 0.00000001)
+			{
+				n = {1,0};
+			}
+			else
+			{
+				n /= l;
+			}
+
+			lineEquation.x = n.x;
+			lineEquation.y = n.y;
+		}
+
+		float getDistanceFromCenter() const
+		{
+			return lineEquation.z;
+		}
+
+		void createFromNormalAndPoint(const glm::vec2 normal, const glm::vec2 point)
+		{
+			float c = -glm::dot(normal, point); // c = -(a*x + b*y)
+			lineEquation = glm::vec3(normal.x, normal.y, c);
+		}
+
+		float getDistanceToPoint(const glm::vec2 &point) const
+		{
+			// Calculate signed distance from point to the line
+			return (lineEquation.x * point.x + lineEquation.y * point.y + lineEquation.z) 
+				/ std::sqrt(lineEquation.x * lineEquation.x + lineEquation.y * lineEquation.y);
+		}
+
+		void createFromRotationAndPoint(const float rotation, const glm::vec2 point)
+		{
+			auto n = rotationToVector(rotation);
+			createFromNormalAndPoint(n, point);
+		}
+
+		float computeEquation(glm::vec2 p) const
+		{
+			return lineEquation.x * p.x + lineEquation.y * p.y + lineEquation.z;
+		}
+
+		bool intersectPoint(glm::vec2 p) const
+		{
+			return computeEquation(p) >= 0;
+		}
+
+		// Get the closest point on the line to the origin (0,0)
+		glm::vec2 getClosestPointToOrigin() const
+		{
+			glm::vec2 normal = getNormal();
+			return -lineEquation.z * normal;
+		}
+
+		// Rotate the normal by 90 degrees to get a direction along the line
+		glm::vec2 getLineVector() const
+		{
+			return glm::vec2(-lineEquation.y, lineEquation.x);
+		}
+	};
+
+	struct Collider
+	{
+		union
+		{
+			struct
+			{
+				glm::vec2 size;
+			}box;
+
+			struct
+			{
+				float radius;
+			}circle;
+	
+		} collider = {};
+
+		unsigned char type = 0;
+
+		float computeMass();
+
+		float computeMomentOfInertia(float mass);
+	};
+
+	enum ColliderType
+	{
+		ColliderNone = 0,
+		ColliderCircle,
+		ColliderBox,
+		ColliderHalfSpace,
+	};
+
+	Collider createBoxCollider(glm::vec2 size);
+
+	Collider createCircleCollider(float r);
+
+	struct Body
+	{
+		//we use center position
+		MotionState motionState;
+
+		Collider collider = {};
+
+		float elasticity = 0.2;
+		float staticFriction = 0.5;
+		float dynamicFriction = 0.4;
+
+		AABB getAABB();
+
+		bool intersectPoint(glm::vec2 p, float delta = 0);
+	};
+
+	bool BodyvsBody(Body &A, Body &B, float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint);
+
+	struct PhysicsEngine
+	{
+		std::vector<Body> bodies;
+
+		//this will make the simulation run at fixed intervals of time, making it deterministic.
+		// it is measured in secconds, so if you set it to 0.016, it will be updated 60 times a seccond, 
+		// if you set it to 0.032, it will be updated 30 times a seccond, and a smaller number will get a lot more updates!
+		//you can set it to 0 if you want it to just update with the deltaTime;
+		float setFixedTimeStamp = 0.016;
+		float maxAccumulated = 0.32;
+		int collisionChecksCount = 8;
+
+		float _fixedTimeAccumulated = 0;
+		void runSimulation(float deltaTime);
+
+		void addBody(glm::vec2 centerPos, Collider collider);
+
+		void addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal);
+	};
+
+	glm::mat2 rotationMatrix(float angle);
+
+	void integrateForces(MotionState &motionState, float mass, float deltaTime);
+
+};

+ 1274 - 0
Pika/thirdparty/ph2d/src/ph2d.cpp

@@ -0,0 +1,1274 @@
+//////////////////////////////////////////////////
+//ph2d.h				0.0.1
+//Copyright(c) 2024 Luta Vlad - Low Level Game Dev
+// please credit me if you want, 
+// and keep this in the code
+//
+//////////////////////////////////////////////////
+
+
+//credits:
+//https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
+
+//todo layers
+//todo apply force,
+//todo optimize collisions using some octrees maybe or something.
+
+
+#include <ph2d/ph2d.h>
+#include <iostream>
+
+constexpr static float MAX_VELOCITY = 10'000;
+constexpr static float MAX_ACCELERATION = 10'000;
+constexpr static float MAX_AIR_DRAG = 100;
+
+void normalizeSafe(glm::vec2 &v)
+{
+	float l = glm::length(v);
+
+	if (l <= 0.00000001)
+	{
+		v = {1,0};
+	}
+	else
+	{
+		v /= l;
+	}
+}
+
+namespace ph2d
+{
+
+	void AABB::rotateAroundCenter(float r)
+	{
+		glm::vec2 newCenter = ph2d::rotateAroundCenter(center(), r);
+		pos = newCenter - size / 2.f;
+	}
+
+	void AABB::getMinMaxPointsRotated(glm::vec2 &outMin, glm::vec2 &outMax, float r)
+	{
+		glm::vec2 minPoint = min();
+		glm::vec2 maxPoint = max();
+		glm::vec2 point3 = {minPoint.x, maxPoint.y};
+		glm::vec2 point4 = {maxPoint.x, minPoint.y};
+
+		glm::vec2 centerP = center();
+
+		minPoint = ph2d::rotateAroundPoint(minPoint, centerP, r);
+		maxPoint = ph2d::rotateAroundPoint(maxPoint, centerP, r);
+		point3 = ph2d::rotateAroundPoint(point3, centerP, r);
+		point4 = ph2d::rotateAroundPoint(point4, centerP, r);
+
+		outMin = minPoint;
+		if (maxPoint.x < outMin.x) { outMin.x = maxPoint.x; }
+		if (point3.x < outMin.x) { outMin.x = point3.x; }
+		if (point4.x < outMin.x) { outMin.x = point4.x; }
+
+		if (maxPoint.y < outMin.y) { outMin.y = maxPoint.y; }
+		if (point3.y < outMin.y) { outMin.y = point3.y; }
+		if (point4.y < outMin.y) { outMin.y = point4.y; }
+
+		outMax = minPoint;
+		if (maxPoint.x > outMax.x) { outMax.x = maxPoint.x; }
+		if (point3.x > outMax.x) { outMax.x = point3.x; }
+		if (point4.x > outMax.x) { outMax.x = point4.x; }
+
+		if (maxPoint.y > outMax.y) { outMax.y = maxPoint.y; }
+		if (point3.y > outMax.y) { outMax.y = point3.y; }
+		if (point4.y > outMax.y) { outMax.y = point4.y; }
+
+	}
+
+	void AABB::getCornersRotated(glm::vec2 corners[4], float r)
+	{
+		corners[0] = min();
+		corners[1] = max();
+		corners[2] = {corners[0].x, corners[1].y};
+		corners[3] = {corners[1].x, corners[0].y};
+
+		glm::vec2 c = center();
+
+		if (r)
+		{
+			corners[0] = rotateAroundPoint(corners[0], c, r);
+			corners[1] = rotateAroundPoint(corners[1], c, r);
+			corners[2] = rotateAroundPoint(corners[2], c, r);
+			corners[3] = rotateAroundPoint(corners[3], c, r);
+		}
+
+	}
+
+	//The second is the circle
+	bool AABBvsCircle(AABB abox, AABB bbox, float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint)
+	{
+		normal = {};
+		// Vector from A to B
+		glm::vec2 n = bbox.center() - abox.center();
+
+		// Closest point on A to center of B
+		glm::vec2 closest = n;
+
+		// Calculate half extents along each axis
+		float x_extent = (abox.max().x - abox.min().x) / 2;
+		float y_extent = (abox.max().y - abox.min().y) / 2;
+
+		// Clamp point to edges of the AABB
+		closest.x = glm::clamp(closest.x, - x_extent, x_extent);
+		closest.y = glm::clamp(closest.y, -y_extent, y_extent);
+
+		bool inside = false;
+		// Circle is inside the AABB, so we need to clamp the circle's center
+		// to the closest edge
+		if (n == closest)
+		{
+
+			inside = true;
+
+			// Find closest axis
+			if (abs(n.x) > abs(n.y))
+			{
+
+				// Clamp to closest extent
+				if (closest.x > 0)
+				{
+					closest.x = x_extent;
+				}
+				else
+				{
+					closest.x = -x_extent;
+				}
+			}
+			// y axis is shorter
+			else
+			{
+				// Clamp to closest extent
+				if (closest.y > 0)
+				{
+					closest.y = y_extent;
+				}
+				else
+				{
+					closest.y = -y_extent;
+				};
+			}
+
+		}
+
+		glm::vec2 normal2 = n - closest;
+		float d = glm::dot(normal2, normal2);
+		float r = bbox.size.x/2.f;
+
+		// Early out of the radius is shorter than distance to closest point and
+		// Circle not inside the AABB
+		if (d > r * r && !inside)
+		{
+			return false;
+		}
+
+
+		// Avoided sqrt until we needed
+		d = sqrt(d);
+
+		// Collision normal needs to be flipped to point outside if circle was
+		// inside the AABB
+		if (inside)
+		{
+			normal = -normal2;
+			penetration = r - d;
+			normalizeSafe(normal);
+
+			glm::vec2 midpoint = (abox.center() + bbox.center()) * 0.5f;
+			//contactPoint = midpoint - (normal * (penetration * 0.5f));
+			contactPoint = bbox.center() + (-normal * (r - std::min(penetration, r) * 0.5f));
+			//contactPoint = bbox.center();
+		}
+		else
+		{
+			normal = normal2;
+			penetration = r - d;
+			normalizeSafe(normal);
+			contactPoint = bbox.center() + (-normal * (r - penetration * 0.5f));
+		}
+
+
+
+		return true;
+	}
+
+	bool HalfSpaceVSCircle(LineEquation line, AABB circle, float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint)
+	{
+		float r = circle.size.x / 2.f;
+		
+		line.normalize();
+
+		normal = line.getNormal();
+
+		glm::vec2 center = circle.center();
+		float distance = line.computeEquation(center);
+
+		penetration = r + distance;
+
+		if (penetration > 0)
+		{
+			contactPoint = center + (normal * (r - penetration * 0.5f));
+			return 1;
+		}
+
+		return 0;
+	}
+
+	//The second is the circle
+	bool OBBvsCircle(AABB abox, float ar, AABB bbox, float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint)
+	{
+		
+		if(ar == 0){ return AABBvsCircle(abox, bbox, penetration, normal, contactPoint); }
+
+		glm::vec2 centerA = abox.center();
+
+		abox.pos -= centerA;
+		bbox.pos -= centerA;
+
+		bbox.rotateAroundCenter(-ar);
+
+		bool rez = AABBvsCircle(abox, bbox, penetration, normal, contactPoint);
+
+		normal = rotateAroundCenter(normal, ar);
+		normalizeSafe(normal);
+		contactPoint = rotateAroundCenter(contactPoint, ar);
+		contactPoint += centerA;
+
+		return rez;
+	}
+
+	bool AABBvsAABB(AABB abox, AABB bbox, float &penetration,
+		glm::vec2 &normal)
+	{
+		// Vector from A to B
+		glm::vec2 n = bbox.center() - abox.center();
+
+		// Calculate half extents along x axis for each object
+		float a_extent = (abox.max().x - abox.min().x) / 2;
+		float b_extent = (bbox.max().x - bbox.min().x) / 2;
+
+		auto aMax = abox.max();
+		auto aMin = abox.min();
+		auto bMax = bbox.max();
+		auto bMin = bbox.min();
+
+		// Calculate overlap on x axis
+		float x_overlap = a_extent + b_extent - abs(n.x);
+
+		// SAT test on x axis
+		if (x_overlap > 0)
+		{
+
+			// Calculate half extents along x axis for each object
+			float a_extent = (abox.max().y - abox.min().y) / 2.f;
+			float b_extent = (bbox.max().y - bbox.min().y) / 2.f;
+
+			// Calculate overlap on y axis
+			float y_overlap = a_extent + b_extent - abs(n.y);
+
+			// SAT test on y axis
+			if (y_overlap > 0)
+			{
+
+				// Find out which axis is axis of least penetration
+				if (x_overlap < y_overlap)
+				{
+
+					// Point towards B knowing that n points from A to B
+					if (n.x < 0)
+					{
+						normal = glm::vec2(-1, 0);
+					}
+					else
+					{
+						normal = glm::vec2(1, 0);
+					}
+
+					penetration = x_overlap;
+					return true;
+				}
+				else
+				{
+
+					// Point toward B knowing that n points from A to B
+					if (n.y < 0)
+					{
+						normal = glm::vec2(0, -1);
+					}
+					else
+					{
+						normal = glm::vec2(0, 1);
+					}
+
+					penetration = y_overlap;
+					return true;
+				}
+
+			}
+
+		}
+
+		return false;
+	}
+
+	float calculatePenetrationAlongOneAxe(glm::vec2 *aPoints, size_t aPointsCount,
+		glm::vec2 *bPoints, size_t bPointsCount, glm::vec2 axeDirection, bool *flipSign)
+	{
+
+		if (aPointsCount <= 0 || bPointsCount <= 0 || !aPoints || !bPoints) { return 0; }
+
+		float d0a = glm::dot(aPoints[0], axeDirection);
+		float d0b = glm::dot(bPoints[0], axeDirection);
+
+		float aMin = d0a;
+		float aMax = d0a;
+		float bMin = d0b;
+		float bMax = d0b;
+
+		for (int i = 1; i < aPointsCount; i++)
+		{
+			glm::vec2 p = aPoints[i];
+			float d = glm::dot(p, axeDirection);
+			if (d > aMax) { aMax = d; }
+			if (d < aMin) { aMin = d; }
+		}
+
+		for (int i = 1; i < bPointsCount; i++)
+		{
+			glm::vec2 p = bPoints[i];
+			float d = glm::dot(p, axeDirection);
+			if (d > bMax) { bMax = d; }
+			if (d < bMin) { bMin = d; }
+		}
+
+		// Calculate overlaps
+		float overlapA = aMax - bMin; // Overlap from A to B
+		float overlapB = bMax - aMin; // Overlap from B to A
+
+		if (overlapA < overlapB)
+		{
+			if (flipSign) { *flipSign = 0; }
+			return overlapA;
+		}
+		else
+		{
+			if (flipSign) { *flipSign = 1; }
+			return overlapB;
+		}
+	}
+
+
+	bool HalfSpaceVSOBB(LineEquation line, AABB bbox, float br, float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint)
+	{
+
+		glm::vec2 corners[4] = {};
+		bbox.getCornersRotated(corners, br);
+
+		float intersections[4] = {};
+		int intersectioncCount = 0;
+		float biggestPenetration = -100000;
+		glm::vec2 intersectedCrners[4] = {};
+
+
+		for (int i = 0; i < 4; i++)
+		{
+			float rez = 0;
+			rez = line.computeEquation(corners[i]);
+
+			if (rez >= 0)
+			{
+				intersections[intersectioncCount] = rez;
+				intersectedCrners[intersectioncCount] = corners[i];
+				intersectioncCount++;
+				
+				if (rez > biggestPenetration)
+				{
+					biggestPenetration = rez;
+				}
+			}
+		}
+
+		if (intersectioncCount)
+		{
+			line.normalize();
+			normal = line.getNormal();
+			penetration = biggestPenetration;
+
+			contactPoint = {};
+
+			for (int i = 0; i < intersectioncCount; i++)
+			{
+				contactPoint += intersectedCrners[i];
+			}
+
+			contactPoint /= intersectioncCount;
+
+			if (intersectioncCount != 4)
+			{
+				contactPoint += normal * (-penetration / 2.f);
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+
+	//a is aabb and b has a rotation
+	bool AABBvsOBB(AABB a, AABB b, float br)
+	{
+
+		glm::vec2 aMin = a.min();
+		glm::vec2 aMax = a.max();
+
+		glm::vec2 bMin = {};
+		glm::vec2 bMax = {};
+		b.getMinMaxPointsRotated(bMin, bMax, br);
+
+
+		if (aMax.x < bMin.x || aMin.x > bMax.x) return false;
+		if (aMax.y < bMin.y || aMin.y > bMax.y) return false;
+
+		//return true;
+
+		//passed first axis test, try the other one
+		{
+			ph2d::AABB newA = a;
+			ph2d::AABB newB = b;
+			float newRotationA = -br;
+
+			glm::vec2 bCenter = b.center();
+			newA.pos -= bCenter;
+			newB.pos -= bCenter;
+
+			newA.rotateAroundCenter(newRotationA);
+
+			glm::vec2 aMin = {};
+			glm::vec2 aMax = {};
+			glm::vec2 bMin = newB.min();
+			glm::vec2 bMax = newB.max();
+
+			newA.getMinMaxPointsRotated(aMin, aMax, newRotationA);
+
+			if (aMax.x < bMin.x || aMin.x > bMax.x) return false;
+			if (aMax.y < bMin.y || aMin.y > bMax.y) return false;
+		}
+
+		return true;
+
+	}
+
+	bool OBBvsOBB(AABB a, float ar, AABB b, float br)
+	{
+		//move A in center.
+		glm::vec2 aPos = a.center();
+		a.pos -= aPos;
+		b.pos -= aPos;
+
+		//we rotate both cubes so now a is axis aligned
+		b.rotateAroundCenter(-ar);
+		br -= ar;
+
+		return AABBvsOBB(a, b, br);
+	}
+
+	bool OBBvsOBB(AABB a, float ar, AABB b, float br,
+		float &penetration, glm::vec2 &normal, glm::vec2 &contactPoint)
+	{
+		penetration = 0;
+		normal = {0,0};
+
+		glm::vec2 cornersA[4] = {};
+		glm::vec2 cornersB[4] = {};
+		a.getCornersRotated(cornersA, ar);
+		b.getCornersRotated(cornersB, br);
+
+		glm::vec2 axes[4] = {
+			 rotateAroundCenter({0, 1}, ar), // Normal of A's first edge
+			 rotateAroundCenter({1, 0}, ar), // Normal of A's second edge
+			 rotateAroundCenter({0, 1}, br), // Normal of B's first edge
+			 rotateAroundCenter({1, 0}, br)  // Normal of B's second edge
+		};
+
+		// Initialize the minimum penetration depth
+		float minPenetration = FLT_MAX;
+		glm::vec2 minPenetrationAxis = {};
+		bool flipSign = 0;
+
+		// Test each axis
+		for (int i = 0; i < 4; ++i)
+		{
+			bool flip = 0;
+			float penetrationDepth = calculatePenetrationAlongOneAxe(
+				cornersA, 4, cornersB, 4, axes[i], &flip);
+
+			// If there's no overlap along this axis, shapes are not colliding
+			if (penetrationDepth < 0.0f)
+			{
+				return false; // No collision
+			}
+
+			// Find the axis of least penetration
+			if (penetrationDepth < minPenetration)
+			{
+				minPenetration = penetrationDepth;
+				minPenetrationAxis = axes[i];
+				flipSign = flip;
+			}
+		}
+
+		penetration = minPenetration;
+		normal = glm::normalize(minPenetrationAxis);
+		if (flipSign) { normal = -normal; }
+
+
+		//contactPoint
+		// Midpoint between the two centers
+		glm::vec2 midpoint = (a.center() + b.center()) * 0.5f;
+		// Adjust by half of the penetration depth along the collision normal
+		contactPoint = midpoint - (normal * (penetration * 0.5f));
+
+		return true;
+	}
+
+
+	bool AABBvsAABB(AABB a, AABB b, float delta)
+	{
+		glm::vec2 aMax = a.max() + glm::vec2(delta, delta);
+		glm::vec2 bMax = b.max() + glm::vec2(delta, delta);
+
+		glm::vec2 aMin = a.min() - glm::vec2(delta, delta);
+		glm::vec2 bMin = b.min() - glm::vec2(delta, delta);
+
+		if (aMax.x < bMin.x || aMin.x > bMax.x) return false;
+		if (aMax.y < bMin.y || aMin.y > bMax.y) return false;
+
+		return true;
+	}
+
+	bool AABBvsPoint(AABB a, glm::vec2 b, float delta)
+	{
+		glm::vec2 aMin = a.min() - glm::vec2(delta, delta);
+		glm::vec2 aMax = a.max() + glm::vec2(delta, delta);
+
+		if (
+			aMin.x < b.x && aMax.x > b.x &&
+			aMin.y < b.y && aMax.y > b.y)
+		{
+			return true;
+		}
+
+		return false;
+	}
+
+	glm::vec2 rotateAroundCenter(glm::vec2 in, float r)
+	{
+		float c = std::cos(-r);
+		float s = std::sin(-r);
+		return glm::vec2(in.x * c - in.y * s, in.x * s + in.y * c);
+	}
+
+	glm::vec2 rotateAroundPoint(glm::vec2 in, glm::vec2 centerReff, float r)
+	{
+		in -= centerReff;
+		in = rotateAroundCenter(in, r);
+		in += centerReff;
+
+		return in;
+	}
+
+	bool OBBvsPoint(AABB a, float rotation, glm::vec2 b, float delta)
+	{
+		if (rotation == 0)
+		{
+			return AABBvsPoint(a, b, delta);
+		}
+
+		//moved the cube in the center of the screen.
+		glm::vec2 pos = a.center();
+		a.pos -= pos;
+		b -= pos;
+
+		b = rotateAroundCenter(b, -rotation);
+
+		return AABBvsPoint(a, b, delta);
+	}
+
+	bool CircleVsPoint(glm::vec2 pos, float r, glm::vec2 p, float delta)
+	{
+		glm::vec2 dist = pos - p;
+
+		float rSquared = (r + delta) * (r + delta);
+		float distSquared = glm::dot(dist, dist);
+
+		return distSquared < rSquared;
+	}
+
+	bool CirclevsCircle(Circle a, Circle b,
+		float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint
+		)
+	{
+		float r = a.r + b.r;
+		float rSquared = r * r;
+		float distanceSquared = ((a.center.x - b.center.x) * (a.center.x - b.center.x)
+			+ (a.center.y - b.center.y) * (a.center.y - b.center.y));
+
+		bool rez = rSquared > distanceSquared;
+
+		if(rez)
+		{
+			normal = b.center - a.center;
+			normalizeSafe(normal);
+			penetration = r - sqrt(distanceSquared);
+
+			contactPoint = a.center + normal * (a.r - penetration / 2.f);
+		}
+
+		return rez;
+	}
+
+	bool BodyvsBody(Body &A, Body &B, float &penetration,
+		glm::vec2 &normal, glm::vec2 &contactPoint)
+	{
+
+		if (A.collider.type == ph2d::ColliderCircle &&
+			B.collider.type == ph2d::ColliderCircle
+			)
+		{
+
+			return ph2d::CirclevsCircle(
+				glm::vec3(A.motionState.pos, A.collider.collider.circle.radius),
+				glm::vec3(B.motionState.pos, B.collider.collider.circle.radius),
+				penetration, normal, contactPoint);
+			
+		}
+		else if (A.collider.type == ph2d::ColliderBox &&
+			B.collider.type == ph2d::ColliderBox)
+		{
+			
+			auto abox = A.getAABB();
+			auto bbox = B.getAABB();
+
+			return ph2d::OBBvsOBB(
+				abox, A.motionState.rotation, bbox,
+				B.motionState.rotation,
+				penetration, normal, contactPoint);
+
+		}
+
+		else if (A.collider.type == ph2d::ColliderBox &&
+			B.collider.type == ph2d::ColliderCircle)
+		{
+
+			auto abox = A.getAABB();
+			auto bbox = B.getAABB();
+
+			return ph2d::OBBvsCircle(
+				abox, A.motionState.rotation, bbox, penetration, normal, contactPoint);
+
+		}
+		else if (A.collider.type == ph2d::ColliderCircle &&
+			B.collider.type == ph2d::ColliderBox)
+		{
+
+			auto abox = A.getAABB();
+			auto bbox = B.getAABB();
+
+			return ph2d::OBBvsCircle(
+				bbox, B.motionState.rotation, abox, penetration, normal, contactPoint);
+
+		}
+
+		else if (A.collider.type == ph2d::ColliderHalfSpace &&
+			B.collider.type == ph2d::ColliderCircle)
+		{
+
+			auto bbox = B.getAABB();
+
+			LineEquation lineEquation;
+			lineEquation.createFromRotationAndPoint(A.motionState.rotation,
+				A.motionState.pos);
+
+			return ph2d::HalfSpaceVSCircle(
+				lineEquation, bbox, penetration, normal, contactPoint);
+		}
+		else if (A.collider.type == ph2d::ColliderCircle &&
+			B.collider.type == ph2d::ColliderHalfSpace)
+		{
+
+			auto abox = A.getAABB();
+
+			LineEquation lineEquation;
+			lineEquation.createFromRotationAndPoint(B.motionState.rotation,
+				B.motionState.pos);
+
+			return ph2d::HalfSpaceVSCircle(
+				lineEquation, abox, penetration, normal, contactPoint);
+		}
+
+		else if (A.collider.type == ph2d::ColliderHalfSpace &&
+			B.collider.type == ph2d::ColliderBox)
+		{
+			auto bbox = B.getAABB();
+
+			LineEquation lineEquation;
+			lineEquation.createFromRotationAndPoint(A.motionState.rotation,
+				A.motionState.pos);
+
+			return ph2d::HalfSpaceVSOBB(
+				lineEquation, bbox, B.motionState.rotation,
+				penetration, normal, contactPoint);
+		}
+		else if (A.collider.type == ph2d::ColliderBox &&
+			B.collider.type == ph2d::ColliderHalfSpace)
+		{
+			auto abox = A.getAABB();
+
+			LineEquation lineEquation;
+			lineEquation.createFromRotationAndPoint(B.motionState.rotation,
+				B.motionState.pos);
+
+			return ph2d::HalfSpaceVSOBB(
+				lineEquation, abox, A.motionState.rotation, penetration, normal, contactPoint);
+		}
+
+		return 0;
+	}
+
+	//todo make sure drag can't be stronger than speed!
+	void applyDrag(MotionState &motionState)
+	{
+		glm::vec2 dragForce = 0.1f * -motionState.velocity * glm::abs(motionState.velocity) / 2.f;
+		float length = glm::length(dragForce);
+		if (length)
+		{
+			if (length > MAX_AIR_DRAG)
+			{
+				dragForce /= length;
+				dragForce *= MAX_AIR_DRAG;
+			}
+		
+			motionState.acceleration += dragForce;
+		}
+	}
+
+	void integrateForces(MotionState &motionState, float deltaTime)
+	{
+
+		if (motionState.mass == 0 || motionState.mass == INFINITY)
+		{
+			motionState.acceleration = {};
+			motionState.velocity = {};
+		}
+		else
+		{
+			//linear motion
+			motionState.acceleration = glm::clamp(motionState.acceleration,
+				glm::vec2(-MAX_ACCELERATION), glm::vec2(MAX_ACCELERATION));
+
+			//Symplectic Euler
+			motionState.velocity += motionState.acceleration * deltaTime * 0.5f;
+			motionState.velocity = glm::clamp(motionState.velocity, glm::vec2(-MAX_VELOCITY), glm::vec2(MAX_VELOCITY));
+
+			motionState.pos += motionState.velocity * deltaTime;
+
+			motionState.velocity += motionState.acceleration * deltaTime * 0.5f;
+			motionState.velocity = glm::clamp(motionState.velocity, glm::vec2(-MAX_VELOCITY), glm::vec2(MAX_VELOCITY));
+
+			if (std::fabs(motionState.velocity.x) < 0.00001) { motionState.velocity.x = 0; }
+			if (std::fabs(motionState.velocity.y) < 0.00001) { motionState.velocity.y = 0; }
+
+			motionState.acceleration = {};
+		}
+
+		if (motionState.momentOfInertia == 0 || motionState.momentOfInertia == INFINITY)
+		{
+			motionState.angularVelocity = 0;
+			motionState.torque = 0;
+		}
+		else
+		{
+			//rotation
+			motionState.angularVelocity += motionState.torque * (1.f/motionState.momentOfInertia) * deltaTime;
+			motionState.rotation += motionState.angularVelocity * deltaTime;
+			motionState.torque = 0;
+		}
+		
+	}
+
+
+	glm::mat2 rotationMatrix(float angle)
+	{
+		float c = cos(angle);
+		float s = sin(angle);
+
+		return glm::mat2(
+			{
+				c, -s,
+				s, c
+			});
+	}
+
+	Collider createBoxCollider(glm::vec2 size)
+	{
+		Collider c;
+		c.type = ColliderBox;
+
+		c.collider.box.size = size;
+
+		return c;
+	}
+
+	Collider createCircleCollider(float r)
+	{
+		Collider c;
+		c.type = ColliderCircle;
+
+		c.collider.circle.radius = r;
+
+		return c;
+	}
+
+	float Collider::computeMass()
+	{
+		switch (type)
+		{
+			case ColliderCircle:
+			return (collider.circle.radius * collider.circle.radius * 3.1415);
+			
+			case ColliderBox:
+			return collider.box.size.x * collider.box.size.y;
+
+			default:
+			return 0;
+		}
+	}
+
+	float Collider::computeMomentOfInertia(float mass)
+	{
+		switch (type)
+		{
+
+		case ColliderCircle:
+		return (collider.circle.radius * collider.circle.radius * mass * 0.5f);
+
+		case ColliderBox:
+		return mass * (collider.box.size.x * collider.box.size.x + 
+			collider.box.size.y * collider.box.size.y) * (1.f/12.f);
+
+		default:
+		return 0;
+		}
+
+	}
+
+
+};
+
+float PythagoreanSolve(float fA, float fB)
+{
+	return std::sqrt(fA * fA + fB * fB);
+}
+
+bool overlap(ph2d::Body &a, ph2d::Body &b)
+{
+
+	
+
+	//todo
+	return 0;
+}
+
+float cross(glm::vec2 a, glm::vec2 b)
+{
+	return a.x * b.y - a.y * b.x;
+}
+
+// More exotic (but necessary) forms of the cross product
+// with a vector a and scalar s, both returning a vector
+glm::vec2 cross(glm::vec2 a, float s)
+{
+	return glm::vec2(s * a.y, -s * a.x);
+}
+
+glm::vec2 cross(float s, glm::vec2 a)
+{
+	return glm::vec2(-s * a.y, s * a.x);
+}
+
+
+void ph2d::MotionState::applyImpulseObjectPosition(glm::vec2 impulse, glm::vec2 contactVector)
+{
+	if (mass != 0 && mass != INFINITY )
+	{
+		velocity += (1.0f / mass) * impulse;
+	}
+
+	//if (momentOfInertia != 0 && momentOfInertia != INFINITY)
+	//{
+	//	angularVelocity -= (1.0f / momentOfInertia) * cross(contactVector, impulse);
+	//}
+}
+
+void ph2d::MotionState::applyImpulseWorldPosition(glm::vec2 impulse, glm::vec2 contactVectorWorldPos)
+{
+	glm::vec2 relVector = contactVectorWorldPos - pos;
+	applyImpulseObjectPosition(impulse, relVector);
+}
+
+
+
+void ph2d::PhysicsEngine::runSimulation(float deltaTime)
+{
+
+	int counter = 0;
+	if (setFixedTimeStamp <= 0)
+	{
+		_fixedTimeAccumulated = 0;
+		counter = 1;
+	}
+	else
+	{
+		_fixedTimeAccumulated += deltaTime;
+
+		_fixedTimeAccumulated = std::min(_fixedTimeAccumulated, maxAccumulated);
+		
+
+		while (_fixedTimeAccumulated > setFixedTimeStamp)
+		{
+			_fixedTimeAccumulated -= setFixedTimeStamp;
+			counter++;
+		}
+
+		deltaTime = setFixedTimeStamp;
+	}
+
+	for (int currentIteration = 0; currentIteration < counter; currentIteration++)
+	{
+		auto positionalCorrection = [&](Body &A, Body &B, glm::vec2 n,
+			float penetrationDepth)
+		{
+
+			float massInverseA = 1.f / A.motionState.mass;
+			float massInverseB = 1.f / B.motionState.mass;
+
+			if (A.motionState.mass == 0 || A.motionState.mass == INFINITY) { massInverseA = 0; }
+			if (B.motionState.mass == 0 || B.motionState.mass == INFINITY) { massInverseB = 0; }
+
+			const float percent = 0.40; // usually 20% to 80%
+			const float slop = 0.01; // usually 0.01 to 0.1 
+
+			glm::vec2 correction = (glm::max(penetrationDepth - slop, 0.0f) / (massInverseA + massInverseB)) * percent * n;
+
+			A.motionState.pos -= massInverseA * correction;
+			B.motionState.pos += massInverseB * correction;
+		};
+
+		auto applyFriction = [&](Body &A, Body &B, glm::vec2 tangent, glm::vec2 rv,
+			float aInverseMass, float bInverseMass, float j, glm::vec2 rContactA,
+			glm::vec2 rContactB, glm::vec2 contactPoint)
+		{
+
+			float momentOfInertiaInverseA = 1.f / A.motionState.momentOfInertia;
+			float momentOfInertiaInverseB = 1.f / B.motionState.momentOfInertia;
+			if (A.motionState.momentOfInertia == 0 || A.motionState.momentOfInertia == INFINITY) { momentOfInertiaInverseA = 0; }
+			if (B.motionState.momentOfInertia == 0 || B.motionState.momentOfInertia == INFINITY) { momentOfInertiaInverseB = 0; }
+
+			//remove moment of inertia
+			momentOfInertiaInverseA = 0;
+			momentOfInertiaInverseB = 0;
+
+			// Solve for magnitude to apply along the friction vector
+			float jt = -glm::dot(rv, tangent);
+			jt = jt / (aInverseMass + bInverseMass)
+				+
+				(std::pow(cross(rContactA, rv), 2) * momentOfInertiaInverseA) +
+				(std::pow(cross(rContactB, rv), 2) * momentOfInertiaInverseB)
+				;
+
+			// PythagoreanSolve = A^2 + B^2 = C^2, solving for C given A and B
+			// Use to approximate mu given friction coefficients of each body
+			float mu = PythagoreanSolve(A.staticFriction, B.staticFriction);
+
+			// Clamp magnitude of friction and create impulse vector
+			//(Coulomb's Law) Ff<=Fn
+			glm::vec2 frictionImpulse = {};
+			if (abs(jt) < j * mu)
+			{
+				frictionImpulse = jt * tangent;
+			}
+			else
+			{
+				float dynamicFriction = PythagoreanSolve(A.dynamicFriction, B.dynamicFriction);
+				frictionImpulse = -j * tangent * dynamicFriction;
+			}
+
+			// Apply
+			//A.motionState.velocity -= (aInverseMass)*frictionImpulse;
+			//B.motionState.velocity += (bInverseMass)*frictionImpulse;
+
+			//A.motionState.applyImpulseWorldPosition(-frictionImpulse, contactPoint);
+			//B.motionState.applyImpulseWorldPosition( frictionImpulse, contactPoint);
+
+
+		};
+
+		auto impulseResolution = [&](Body &A, Body &B, glm::vec2 normal,
+			float velAlongNormal, float penetrationDepth, glm::vec2 contactPoint)
+		{
+
+			//calculate elasticity
+			float e = std::min(A.elasticity, B.elasticity);
+
+			float massInverseA = 1.f / A.motionState.mass;
+			float massInverseB = 1.f / B.motionState.mass;
+			if (A.motionState.mass == 0 || A.motionState.mass == INFINITY) { massInverseA = 0; }
+			if (B.motionState.mass == 0 || B.motionState.mass == INFINITY) { massInverseB = 0; }
+
+			float momentOfInertiaInverseA = 1.f / A.motionState.momentOfInertia;
+			float momentOfInertiaInverseB = 1.f / B.motionState.momentOfInertia;
+			if (A.motionState.momentOfInertia == 0 || A.motionState.momentOfInertia == INFINITY) { momentOfInertiaInverseA = 0; }
+			if (B.motionState.momentOfInertia == 0 || B.motionState.momentOfInertia == INFINITY) { momentOfInertiaInverseB = 0; }
+
+
+			glm::vec2 rContactA = contactPoint - A.motionState.pos;
+			glm::vec2 rContactB = contactPoint - B.motionState.pos;
+
+			
+			//float inertiaDivisorA = 0;
+			//float inertiaDivisorB = 0;
+
+			float inertiaDivisorA = std::pow(cross(rContactA, normal), 2) * momentOfInertiaInverseA;
+			float inertiaDivisorB = std::pow(cross(rContactB, normal), 2) * momentOfInertiaInverseB;
+
+			if (massInverseA == 0 && massInverseB == 0
+				&& inertiaDivisorA == 0 && inertiaDivisorB == 0
+				)
+			{
+				//nothing will move, no need to compute anything
+				return;
+			}
+
+			//remove moment of inertia
+			inertiaDivisorA = 0;
+			inertiaDivisorB = 0;
+
+			// Calculate impulse scalar
+			float j = -(1.f + e) * velAlongNormal;
+			j /= (massInverseA + massInverseB + 
+				inertiaDivisorA +
+				inertiaDivisorB);
+
+			// Apply impulse
+			glm::vec2 impulse = j * normal;
+			//A.motionState.velocity -= massInverseA * impulse;
+			//B.motionState.velocity += massInverseB * impulse;
+
+			A.motionState.applyImpulseWorldPosition(-impulse, contactPoint);
+			B.motionState.applyImpulseWorldPosition( impulse, contactPoint);
+
+			{
+
+				// Re-calculate relative velocity after normal impulse
+				// is applied (impulse from first article, this code comes
+				// directly thereafter in the same resolve function)
+
+				glm::vec2 rv = B.motionState.velocity - A.motionState.velocity;
+
+				// Solve for the tangent vector
+				glm::vec2 tangent = rv - glm::dot(rv, normal) * normal;
+
+				float rangentSize = glm::length(tangent);
+				
+				if (rangentSize > 0.001)
+				{
+					tangent /= rangentSize;
+
+					applyFriction(A, B, tangent, rv, massInverseA, massInverseB, j,
+						rContactA, rContactB, contactPoint);
+				}
+
+			}
+
+
+		};
+
+		size_t bodiesSize = bodies.size();
+		for (int i = 0; i < bodiesSize; i++)
+		{
+
+			//applyDrag(bodies[i].motionState);
+
+			//detect colisions
+			for(int _ = 0; _ < collisionChecksCount; _++)
+			for (int j = 0; j < bodiesSize; j++)
+			{
+				//break;
+				if (i == j) { continue; }
+
+				auto &A = bodies[i];
+				auto &B = bodies[j];
+
+				glm::vec2 normal = {};
+				glm::vec2 contactPoint = {};
+				float penetration = 0;
+
+				if (BodyvsBody(A, B, penetration, normal, contactPoint))
+				{
+					glm::vec2 relativeVelocity = B.motionState.velocity -
+						A.motionState.velocity;
+					float velAlongNormal = glm::dot(relativeVelocity, normal);
+
+					// Do not resolve if velocities are separating
+					if (velAlongNormal > 0)
+					{
+
+					}
+					else
+					{
+						impulseResolution(A, B, normal, velAlongNormal, penetration, contactPoint);
+					}
+
+					if (_ == collisionChecksCount - 1
+						)
+					{
+						positionalCorrection(A, B, normal, penetration);
+					}
+				}
+
+			}
+
+			integrateForces(bodies[i].motionState, deltaTime);
+			bodies[i].motionState.lastPos = bodies[i].motionState.pos;
+		}
+
+	};
+
+}
+
+
+void ph2d::PhysicsEngine::addBody(glm::vec2 centerPos, Collider collider)
+{
+
+	Body body;
+	body.motionState.setPos(centerPos);
+	body.collider = collider;
+	body.motionState.mass = collider.computeMass();
+	body.motionState.momentOfInertia = collider.computeMomentOfInertia(body.motionState.mass);
+
+	bodies.push_back(body);
+
+}
+
+
+float ph2d::vectorToRotation(const glm::vec2 &vector)
+{
+	// Handle zero vector by defaulting to 0 radians (pointing up)
+	if (glm::length(vector) == 0.0f)
+	{
+		return 0.0f;
+	}
+	
+	// Calculate angle using atan2
+	float angle = atan2(-vector.x, vector.y);
+
+	// Adjust to ensure 0 radians corresponds to the up vector (0, 1)
+	return angle;
+}
+
+glm::vec2 ph2d::rotationToVector(float rotation)
+{
+	// Calculate direction vector using sine and cosine
+	float x = sin(rotation);
+	float y = cos(rotation);
+	return glm::normalize(glm::vec2(-x, y));
+}
+
+void ph2d::PhysicsEngine::addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal)
+{
+	Body body;
+	body.motionState.setPos(position);
+	body.collider.type = ColliderType::ColliderHalfSpace;
+	body.motionState.mass = 0;
+	body.motionState.momentOfInertia = 0;
+
+	body.motionState.rotation = vectorToRotation(normal);
+	bodies.push_back(body);
+
+}
+
+
+ph2d::AABB ph2d::Body::getAABB()
+{
+
+	switch (collider.type)
+	{
+
+	case ColliderCircle:
+	{
+		glm::vec4 rez;
+		rez.x = motionState.pos.x;
+		rez.y = motionState.pos.y;
+
+		rez.x -= collider.collider.circle.radius;
+		rez.y -= collider.collider.circle.radius;
+
+		rez.z = collider.collider.circle.radius * 2.f;
+		rez.w = collider.collider.circle.radius * 2.f;
+
+		return rez;
+	};
+	break;
+
+	case ColliderBox:
+	{
+		glm::vec4 rez;
+		rez.x = motionState.pos.x;
+		rez.y = motionState.pos.y;
+
+		rez.x -= collider.collider.box.size.x / 2.f;
+		rez.y -= collider.collider.box.size.y / 2.f;
+
+		rez.z = collider.collider.box.size.x;
+		rez.w = collider.collider.box.size.y;
+
+		return rez;
+	}
+	break;
+
+	}
+
+	return {};
+
+}
+
+bool ph2d::Body::intersectPoint(glm::vec2 p, float delta)
+{
+	switch (collider.type)
+	{
+
+	case ColliderCircle:
+	{
+		return CircleVsPoint(motionState.pos, collider.collider.circle.radius, p, delta);
+	};
+	break;
+
+	case ColliderBox:
+	{
+		return OBBvsPoint(getAABB(), motionState.rotation, p, delta);
+	}
+	break;
+
+	}
+
+	return {};
+}
+

Some files were not shown because too many files changed in this diff