6.4 선 그리기 알고리즘

2023. 6. 6. 15:14개인공부/게임수학

 

라인그리는 함수를 콘솔창에서 구현

 


브레젠험 알고리즘을 구현하는 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 
void WindowsRSI::DrawLine(const Vector2& InStartPos, const Vector2& InEndPos, const LinearColor& InColor)
{
    Vector2 clippedStart = InStartPos;
    Vector2 clippedEnd = InEndPos;
    Vector2 screenExtend = Vector2(_ScreenSize.X, _ScreenSize.Y) * 0.5f;
    Vector2 minScreen = -screenExtend;
    Vector2 maxScreen = screenExtend;
    
    // 코헨 서덜랜드 직선 클리핑 알고리즘을 구현한 함수 
    // 시작지점과 마지막지점을 그리기 영역에 맞게 조절하는 함수
    if (!CohenSutherlandLineClip(clippedStart, clippedEnd, minScreen, maxScreen))
    {
        // 그리기 밖영역인 경우
        return;
    }
 
    // Vector2 -> ScreenPoint 구조체로 형변환
    ScreenPoint startPosition = ScreenPoint::ToScreenCoordinate(_ScreenSize, clippedStart);
    ScreenPoint endPosition = ScreenPoint::ToScreenCoordinate(_ScreenSize, clippedEnd);
 
    // w,h 
    int width = endPosition.X - startPosition.X;
    int height = endPosition.Y - startPosition.Y;
 
    bool isGradualSlope = (Math::Abs(width) >= Math::Abs(height));
 
    int dx = (width >= 0) ? 1 : -1;
    int dy = (height >= 0) ? 1 : -1;
    
    // 판별식에 사용하는 변수
    int fw = dx * width;
    int fh = dy * height;
 
    // 최초 사용할 판별식 f를 저장한다.
    int f = isGradualSlope ? fh * 2 - fw : 2 * fw - fh;
    // 선이 변화없이 진행되는 경우에 사용할 판별식 조정값을 isGradualSlop에 따라서 구함
    int f1 = isGradualSlope ? 2 * fh : 2 * fw;
    int f2 = isGradualSlope ? 2 * (fh - fw) : 2 * (fw - fh);
    
    // 최초의 선 그리기를 시작할 지점을 변수 x와 y에 각각 보관한다.
    int x = startPosition.X;
    int y = startPosition.Y;
 
    // isGradualSlope 값에 따라 로직을 분기한다. 해당 값이 참이면 1,4,5,8 팔분면의 선 그리기가 진행된다.
    if (isGradualSlope)
    {
        // 끝점에 도달할 때까지 로직을 계속 반복한다.
        while (x != endPosition.X)
        {
            // 지정된 색상으로 스크린 좌표에 점을 찍는다.
            SetPixel(ScreenPoint(x, y), InColor);
 
            // 판벽식이 0보다 작으면 f1값을 사용해 판별식을 갱신한다.
            if (f < 0)
            {
                f += f1;
            }
            // 판별식이 0보다 크거나 같으면 f2값을 사용해 판별식을 갱신한다.
            else
            {
                f += f2;
                y += dy;
            }
 
            // 다음 픽셀로 이동한다.
            x += dx;
        }
    }
    // isGradualSlope 값이 거짓이면 2,3,6,7 팔분면의 선 그리기를 진행한다.
    else
    {
        while (y != endPosition.Y)
        {
            SetPixel(ScreenPoint(x, y), InColor);
 
            if (f < 0)
            {
                f += f1;
            }
            else
            {
                f += f2;
                x += dx;
            }
 
            y += dy;
        }
    }
}
cs