수학/이득우의 게임 수학 - 실습 예제

삼각함수로 하트 그리기

monstro 2025. 8. 24. 23:56
728x90
반응형

하트 방정식 중 하나

 

하트를 그리는 하트 방정식은 많은 종류가 존재한다

그 중에서 위의 방정식을 사용하여 사용자가 입력한 값을 사용하여 하트를 그려본다

 

- 삼각함수를 사용한 하트 그리기

// 하트의 최종 위치 벡터와 최종 크기
Vector2 currentPosition;
float currentScale = 10.f;

// 매 프레임마다 호출하는 함수
void SoftRenderer::Update2D(float InDeltaSeconds)
{
	// 사용자로부터 입력을 받기 위한 레퍼런스
	auto& g = Get2DGameEngine();
	const InputManager& input = g.GetInputManager();

	// 로컬 변수
	// 하트를 이동시키는 속도 / 하트의 최소 크기 / 하트의 최대 크기 / 하트의 크기를 조절하는 속도
	static float moveSpeed = 100.f;
	static float scaleMin = 5.f;
	static float scaleMax = 20.f;
	static float scaleSpeed = 20.f;
	
	// 사용자로부터 입력값을 받아와 변경할 하트의 위치 벡터 / 하트의 크기 생성
	Vector2 inputVector = Vector2(input.GetAxis(InputAxis::XAxis), input.GetAxis(InputAxis::YAxis)).GetNormalize();
	Vector2 deltaPosition = inputVector * moveSpeed * InDeltaSeconds;
	float deltaScale = input.GetAxis(InputAxis::ZAxis) * scaleSpeed * InDeltaSeconds;

	// 하트의 최종 위치 벡터와 크기를 설정
	currentPosition += deltaPosition;
	currentScale = Math::Clamp(currentScale + deltaScale, scaleMin, scaleMax);
}

// 화면에 렌더링하는 함수
void SoftRenderer::Render2D()
{
	// 화면에 렌더하기 위해 가져올 레퍼런스
	auto& r = GetRenderer();
	const auto& g = Get2DGameEngine();

	// 배경에 격자 그리기
	DrawGizmo2D();

	// 로컬 변수
	// 현재 각도 / 각도를 서서히 증가시킬 값 / 하트를 구성하는 점을 저장할 컨테이너
	float rad = 0.f;
	static float increment = 0.001f;
	static std::vector<Vector2> hearts;

	// 컨테이너에 하트를 구성하는 점들을 저장하는 로직
	if (hearts.empty())
	{
		// sin 함수와 cos 함수의 정의역인 0과 2π의 범위만을 순회
		for (rad = 0.f; rad < Math::TwoPI; rad += increment)
		{
			float sin = sinf(rad);
			float cos = cosf(rad);
			float cos2 = cosf(2 * rad);
			float cos3 = cosf(3 * rad);
			float cos4 = cosf(4 * rad);
            
			// 하트 방정식 사용
			float x = 16.f * sin * sin * sin;
			float y = 13 * cos - 5 * cos2 - 2 * cos3 - cos4;
			hearts.push_back(Vector2(x, y));
		}
	}
	
	// 하트를 구성하는 점들을 파란색으로 칠함
	for (auto const& v : hearts)
	{
		r.DrawPoint(v * currentScale + currentPosition, LinearColor::Blue);
	}

	// 현재 하트의 위치벡터와 크기를 화면에 출력
	r.PushStatisticText(std::string("Position : ") + currentPosition.ToString());
	r.PushStatisticText(std::string("Scale : ") + std::to_string(currentScale));
}

 

위와 같이 코드를 구성하였다

하트 방정식 중에서 sin 함수cos 함수를 사용하는 방정식을 사용하므로

인자로 들어갈 수 있는 수는 0에서 2π 사이의 값을 유지해야 한다

 

- 최종 실행 결과

728x90
반응형