공부 일지/C++

[C++] 3.3 질량-용수철 시스템

Roble 2023. 12. 12. 15:26

 

 

Spring Force

Hooke's Law, 질점이 1개일 때

 

L0 : 용수철 원래 길이

L   : 용수철 나중 길이

K  : 용수철의 경직 정도

Fspring : 원래 길이로 돌아가려는 용수철의 힘          ∝        K

 

 

 

 

Hooke's Law, 질점이 2개일 때

 

 

Damping Force

Damper : 두 물체의 상대속도를 줄여준다.

                즉, 두 물체의 속도가 비슷해지도록 만든다 ( 현관문이 쾅 안닫히도록 해주는 그 장치와 같다 )

                스프링이 출렁거리는 정도를 서서히 줄여준다

 

Spring Force : '길이의 차이' 에 의해 작용 됨

Damping Force : '속도의 차이'에 의해 작용 됨

 

덤핑 계수 d : 단위 속도 당 물체의 운동을 방해하는 힘

 

 

 

질점이 1개일 때

F_ij,damping = j로부터 i를 향한 댐핑값

 

Damping Force in 1D :질점이 1개일때, 질점이 아닌 고정된 물체와 질점과의 속도 차이(상대속도)를 0으로 만드려는 힘

 

 

질점이 2개일 때

F_ij,damping = j로부터 i를 향한 댐핑값

 

외부의 힘을 받아 움직이는 두 질점의 상대속도를 0으로 만드는 힘

 

내적해서 나온 결과값이 크기를 결정한다.

 

 

 

스프링 구현하기

F_ij,spring과 F_ij,damping을 더한 힘으로 고정되지 않은 공(자유낙하 하고 있는 공)을 스프링 힘에 의해 원래 위치로 돌아가게끔 만들기

#include "Game2D.h"
#include "Examples/PrimitivesGallery.h"
#include "RandomNumberGenerator.h"
#include "RigidCircle.h"
#include <vector>
#include <memory>

namespace jm
{
	class Example : public Game2D
	{
	public:
		RigidCircle rb0, rb1;

		Example()
			: Game2D()
		{
			reset();
		}

		void reset()
		{
			// Initial position and velocity
			rb0.pos = vec2(0.0f, 0.5f);
			rb0.vel = vec2(0.0f, 0.0f);
			rb0.color = Colors::hotpink;
			rb0.radius = 0.03f;
			rb0.mass = 1.0f;

			rb1.pos = vec2(0.5f, 0.5f);
			rb1.vel = vec2(0.0f, 0.0f);
			rb1.color = Colors::yellow;
			rb1.radius = 0.03f;
			rb1.mass = rb0.mass * std::pow(rb1.radius / rb0.radius, 2.0f);
		}

		void drawWall()
		{
			setLineWidth(5.0f);
			drawLine(Colors::blue, { -1.0f, -1.0f }, Colors::blue, { 1.0f, -1.0f });
			drawLine(Colors::blue, { 1.0f, -1.0f }, Colors::blue, { 1.0f, 1.0f });
			drawLine(Colors::blue, { -1.0f, -1.0f }, Colors::blue, { -1.0f, 1.0f });
		}

		void update() override
		{
			const float dt = getTimeStep() * 0.4f;
			const float epsilon = 0.5f;

			// physics update (Temporarily disabled)
			//rb0.update(dt); 이부분은 필요 없다.
			//rb1.update(dt); 공이 벽에 부딪칠때, 바닥에 부딪칠때를 처리하는 함수였으므로. 이 예제에선 필요 X

			// coefficients
			const vec2 gravity(0.0f, -9.8f);
			const float l0 = 0.5f; // l_0 원래의 초기길이
			const float coeff_k = 100.0f; // 스프링의 딱딱한 정도
			const float coeff_d = 100.0f; // 스프링의 출렁거림을 줄여준다. 속도를 낮추려는 힘.

			// update rb1 (Note: rb0 is fixed)
			{
				const auto distance = (rb1.pos - rb0.pos).getMagnitude();
				const auto direction = (rb1.pos - rb0.pos) / distance;

				// compute stiffness force & damping force
				const auto spring_force = direction * -(distance - l0) * coeff_k  
																+ direction * -(rb1.vel - rb0.vel).getDotProduct(direction) * coeff_d ;

				const auto accel = gravity + spring_force / rb1.mass;

				rb1.vel += accel * dt;
				rb1.pos += rb1.vel * dt;
			}

			// draw
			drawWall();

			// spring
			drawLine(Colors::red, rb0.pos, Colors::red, rb1.pos);

			// mass points
			rb0.draw();
			rb1.draw();

			// reset button
			if (isKeyPressedAndReleased(GLFW_KEY_R)) reset();
		}

	};
}

int main(void)
{
	jm::Example().run();

	return 0;
}