728x90
반응형
- 개요

아핀 변환을 적용하여 2차원 행렬이 아닌, 3차원 행렬을 사용하는 변환은 위와 같다
해당 식을 사용하여 하트의 크기 / 회전 / 이동을 변환한다
- 예제
...
// 화면에 렌더링하는 함수
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())
{
// 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));
}
}
// 아핀 변환을 적용한 크기 변환 행렬 생성
// 행렬을 구성하는 마지막 차원(벡터)은 항상 (0, 0, 1)
Vector3 sBasis1(currentScale, 0.f, 0.f);
Vector3 sBasis2(0.f, currentScale, 0.f);
Vector3 sBasis3 = Vector3::UnitZ;
Matrix3x3 sMatrix(sBasis1, sBasis2, sBasis3);
// 아핀 변환을 적용한 회전 변환 행렬 생성
// 행렬을 구성하는 마지막 차원(벡터)은 항상 (0, 0, 1)
float sin = 0.f, cos = 0.f;
Math::GetSinCos(sin, cos, currentDegree);
Vector3 rBasis1(cos, sin, 0.f);
Vector3 rBasis2(-sin, cos, 0.f);
Vector3 rBasis3 = Vector3::UnitZ;
Matrix3x3 rMatrix(rBasis1, rBasis2, rBasis3);
// 아핀 변환을 적용한 이동 변환 행렬 생성
// 행렬을 구성하는 마지막 차원(벡터)은 항상 (0, 0, 1)
Vector3 tBasis1 = Vector3::UnitX;
Vector3 tBasis2 = Vector3::UnitY;
Vector3 tBasis3(currentPosition.X, currentPosition.Y, 1.f);
Matrix3x3 tMatrix(tBasis1, tBasis2, tBasis3);
// 모든 아핀 변환을 적용한 행렬들을 곱하여 합성 행렬 생성
// 크기 변환 - 회전 변환 - 이동 변환 순서로 적용
Matrix3x3 finalMatrix = tMatrix * rMatrix * sMatrix;
// 현재 각도를 초기화한 후 색상을 증가시키면서 점에 대응
rad = 0.f;
for (auto const& v : hearts)
{
// 하트를 구성하는 점 벡터를 3차원 벡터로 변환하되, 마지막 차원(벡터)을 1로 설정
Vector3 newV(v.X, v.Y, 1.f);
// 아핀 변환 행렬들을 곱한 합성 행렬 사용
Vector3 finalV = finalMatrix * newV;
// 3차원 벡터를 2차원 벡터로 변환하여 화면에 표현
hsv.H = rad / Math::TwoPI;
r.DrawPoint(finalV.ToVector2(), hsv.ToLinearColor());
rad += increment;
}
// 현재 위치, 크기, 각도를 화면에 출력
r.PushStatisticText(std::string("Position : ") + currentPosition.ToString());
r.PushStatisticText(std::string("Scale : ") + std::to_string(currentScale));
r.PushStatisticText(std::string("Degree : ") + std::to_string(currentDegree));
}
...
아핀 변환을 적용한 크기 변환 행렬 - 회전 변환 행렬 - 이동 변환 행렬의 순서대로 곱하여 합성 행렬을 생성한다
최종 변환된 결과에서 (x, y)값만을 가져와 2차원 행렬로 변환하여 화면에 표시한다
- 최종 실행 결과

728x90
반응형
'수학 > 이득우의 게임 수학 - 실습 예제' 카테고리의 다른 글
| 브레젠험 알고리즘의 구현 (0) | 2025.10.15 |
|---|---|
| 스크린 좌표계 구조 (0) | 2025.10.01 |
| 역행렬을 사용하여 하트의 원본 형태 유지 (0) | 2025.09.17 |
| 행렬을 사용하여 하트의 크기 변환 & 회전 변환 구현 (0) | 2025.09.10 |
| 극좌표계를 활용한 소용돌이 효과 구현 (0) | 2025.08.27 |