삼각함수 회전

CJB_ny·2023년 2월 18일
0

이득우 겜수

목록 보기
2/9
post-thumbnail

4-1 삼각함수

직각 삼각형을 구성하는 세변에서 두변을 뽑아 각각의 비례관계를 나타낸 것을 "삼각비"라 한다.

삼각비에는 대표적으로 sin, cos, tan이 있음.

반지름 길이가 1인 단위원을 그려보면 삼각함수 쉽게 이해할 수 있음.

여기에서 피타고라스 정리를 쓰면은

cos^2θ + sin^2θ = 1 이다.

즉 반지름이 r인 원에서의 빗변은 벡터의 개념으로 보면은 길이가 1인 벡터와 평행하고 길이는 r배 만큼 증가햇으므로, 스칼라 곱에 의해 r * (cosθ, sinθ) 라는 좌표를 갖게된다.

r^2 (cos^2θ + sin^2θ) = r^2
따라서 cos^2θ + sin^2 = 1


삼각함수 성질

코사인 그래프는 좌우 대칭이고

사인 그래프는 원점 대칭이다.

빨간게 cos, 하늘색이 sin 그래프이다.

θ 가 0에 수렴할 수록 cosθ는 1로 가게되고 sinθ은 0으로 가게된다.

π란 ??? ❗❗❗

이번 파트 공부하면서 제일 도움이 많이 되었던 부분이다.

360도라는 큰 단위를 사용을 안하고 단위벡터처럼 간단하게 사용하기 위해서 "호도법"을 사용을 한다.

호도법은 뭐냐?

호의 길이를 기준으로 각을 측정하는 방법을 말한다.

호도법은 호의 길이가 1이 되는 부채꼴의 각을 기준으로 각을 측정한다.


이렇게 radius가 1인 반원을 그린다.

그리고 이것을 + 1한다. 그리고 호를 x축으로 쭉피면은

그 길이가 3.141592... π(파이)가 된다.

180도에 해당하는 반원의 호의 길이가 π(3.14)이다.

거꾸로 호의 길이가 1인 부채꼴의 중심각은 대략 57.2958도 이다.

이 부채꼴의 각이 호도법에서 사용하는 각의 기준인 1rad이다.

1rad = 57도이다.

πrad는? 180도이다. (rad는 앞으로 생략함)

1도 = π / 180 (rad) (== 180도 = π (rad))
1(rad) = 180 / π 도

그래서 30도는 π / 6

45는 π / 4

60도 = π / 3

90도 = π / 2

180도 = π

이렇게 나왔던것이다.

삼각함수로 하트 그리기

  • 하트 방정식

    x = 16sin^3θ
    y = 13 cos(θ) - 5 cos(2θ) - 2 * cos(3θ) - cos(4θ)

// 게임 로직과 렌더링 로직이 공유하는 변수
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 duration = 1.5f;
	static float elapsedTime = 0.f; // 경과 시간

	Vector2 inputVector = Vector2(input.GetAxis(InputAxis::XAxis), input.GetAxis(InputAxis::YAxis)).GetNormalize();
	Vector2 deltaPosition = inputVector * moveSpeed * InDeltaSeconds;

	// 경과 시간과 sin 함수를 활용한 [0, 1] 값의 생성
	elapsedTime += InDeltaSeconds;
	elapsedTime = Math::FMod(elapsedTime, duration);
	float currentRad = (elapsedTime / duration) * Math::TwoPI;
	float alpha = (sinf(currentRad) + 1) * 0.5f;

	// 물체의 최종 상태 설정
	currentPosition += deltaPosition;
	currentScale = Math::Lerp(scaleMin, scaleMax, alpha);
}

경과 시간 elapsedTime에다가 Deltaseconds만큼 더해준다.
그리고 duration으로 나눈 나머지값을 elapsedTime에 넣는데 이렇게하면 값에 0 ~ 1.5로 고정되어버림.

float currentRad = (elapsedTime / duration) * Math::TwoPI;

이부분이 360도 2π를 elapsedTime / duration만큼 진행시키겠다라는 말이다.

즉sin이 0일때부터 360도 까지 진행하는거임 0/1.5 -> 0.1/1.5 ... -> 1.5/1.5 이렇게 진행하다가

1이 되면은 다시 0도로 맞춤 그러면 원점 대칭이라 커졌다 작아졌다를 반복한다.

그리고 currentRad 현재 각도는 (elapsedTime / duration) 에다가 2π를 곱한값을 각도로 설정해준다.

빨간선은 원래 sin그래프 원점 대칭 == 기함수 == 홀함수

초록선은 sin그래프에 1을 더한 그래프

파란선은 선형보간을 위해 초록선에 0.5를 곱한 그래프이다.

Lerp: 선형보간 함수는 0, 1사이의 값을 인자로 받아 최소와 최대값의 중간값을 던지기 때문에 sin그래프를 선형보간함수에 맞추기 위해서 (sin(setha) + 1) * 0.5를 해준것이다.

저 파란선안에서 크기가 sin그래프 모양에 따라 커졌다 작아졌다 하게 하는 것이다.

// 렌더링 로직을 담당하는 함수
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;
	HSVColor hsv(0.f, 1.f, 0.85f);

	// 하트를 구성하는 점 생성
	if (hearts.empty())
	{
		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));
		}
	}

	// 각 값을 초기화한 후 색상을 증가시키면서 점에 대응
	rad = 0.f;
	for (auto const& v : hearts)
	{
		hsv.H = rad / Math::TwoPI;
		r.DrawPoint(v * currentScale + currentPosition, hsv.ToLinearColor());
		rad += increment;
	}

	// 현재 위치와 스케일을 화면에 출력
	r.PushStatisticText(std::string("Position : ") + currentPosition.ToString());
	r.PushStatisticText(std::string("Scale : ") + std::to_string(currentScale));
}

하트 방정식에 해당하는 점들을 hearts에다가 넣어준다음에 위치들을 그려주면 된다.


4.2 삼각함수를 활용한 물체의 회전

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글