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

극좌표계를 활용한 소용돌이 효과 구현

monstro 2025. 8. 27. 12:05
728x90
반응형

- 개요

 

극좌표계회전 동작을 기반으로 설계된 좌표계를 의미한다

원점으로부터 r만큼의 거리에서 각 θ만큼 회전한 좌표 (r, θ)로 표현할 수 있다

 

 

 

위와 같이 데카르트 좌표계에서 극좌표계로, 극좌표계에서 데카르트 좌표계로 변환이 가능하다

 

- 예제

// 소용돌이의 최종 각도
float currentDegree = 0.f;

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

	// 소용돌이의 회전 속도
	static float rotateSpeed = 180.f;

	// 사용자로부터 입력값을 받아와 변경할 소용돌이의 회전 각도 설정
	float deltaDegree = input.GetAxis(InputAxis::WAxis) * rotateSpeed * InDeltaSeconds;

	// 소용돌이의 최종 각도 설정
	currentDegree += deltaDegree;
}

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

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

	// 로컬 변수
    	// 소용돌이를 구성하는 점들을 모아놓은 정사각형의 반지름
    	// 정사각형을 구성하는 점(위치벡터)들을 모아놓은 컨테이너
	static float halfSize = 100.f;
	static std::vector<Vector2> squares;

	// 사각형을 구성하는 점을 생성
	if (squares.empty())
	{
    		// 회전후의 결과가 밀도있어 보이도록 많은 점을 생성
		for (float x = -halfSize; x <= halfSize; x += 0.25f)
		{
			for (float y = -halfSize; y <= halfSize; y += 0.25f)
			{
				squares.push_back(Vector2(x, y));
			}
		}
	}

	// 최종 소용돌이의 각도에 해당하는 사인과 코사인 함수 얻기
	float sin = 0.f, cos = 0.f;
	Math::GetSinCos(sin, cos, currentDegree);

	// 길이에 따라 회전량을 다르게 하기 위해 기준 값을 설정
	static float maxLength = Vector2(_ScreenSize.X, _ScreenSize.Y).Size() * 0.5f;

	// 소용돌이를 구성하는 점들을 표현
	HSVColor hsv(0.f, 1.f, 0.85f);
	for (auto const& v : squares)
	{
		// 데카르트 좌표계를 극좌표계로 변환
		Vector2 polarV = v.ToPolarCoordinate();

		// 극좌표계의 정보로부터 색상을 결정
		if (polarV.Y < 0.f)
		{
			polarV.Y += Math::TwoPI;
		}
		hsv.H = polarV.Y / Math::TwoPI;

		// 극좌표계의 크기 정보로부터 회전량을 결정
		float ratio = polarV.X / maxLength;
		float weight = Math::Lerp(1.f, 5.f, ratio);

		// 극좌표계를 사용하여 회전을 부여
		polarV.Y += Math::Deg2Rad(currentDegree) * weight;

		// 극좌표계를 다시 데카르트 좌표계로 변환
		Vector2 cartesianV = polarV.ToCartesianCoordinate();
		r.DrawPoint(cartesianV, hsv.ToLinearColor());
	}

	// 최종 각도를 화면에 출력
	r.PushStatisticText(std::string("Degree : ") + std::to_string(currentDegree));
}

 

최초의 정사각형 상태의 점들에 점점 회전량을 부여하여 소용돌이 형태로 변경한다

이때 중심에서 멀어지는 점들에 더 많은 회전량을 부여한다

회전은 데카르트 좌표계 -> 극좌표계 -> 데카르트 좌표계의 순서로 렌더링된다

 

- 최종 실행 결과

728x90
반응형