CG 과제로 기존의 그림판의 기능을 확장 시키는 과제를 받았다.

기존 프로그램은 위와 같다. 선, 사각형, 삼각형, 도트, 텍스트 입력 기능을 지원한다.
이 프로그램을 기반으로 추가적으로 기능을 구현하고자 한다.
프로젝트는 팀단위로 실시하게 되었다.
* 도트 기능의 확장
-> 선택한 색으로 나오게 하기
* 별 그리기 기능
* 브러쉬 기능
팀원들은 각자의 구현파트가 있고, 내가 추가할 기능은 위의 세가지이다.
* 팔레트 기능
* 윈도우 확장 및 추가기능
추가적으로 위의 기능들에 대하여는 내가 개인적으로 하고싶어서 하게 되었다.
이번 포스팅에서는 확장기능에 대한 코드를 발췌하여 설명하고, 다음 포스팅에서는 프로그램의 전반적인 동작이 어떻게 이루어지는지에 대하여 포스팅 하겠다.
각 항목을 어떻게 프로그램에 적용시킬지에 대한 궁금증을 가졌다면 다음 포스팅을 참고하면 될 것 같다.
1. 도트 기능의 확장
먼저, 현재 도트기능이 어떻게 작동하는지 보기로 했다.
void drawSquare(int x, int y)
{
        y=wh-y;
        glColor3ub((char)rand() % 256, (char)rand() % 256, (char)rand() % 256);
        glBegin(GL_POLYGON);
                glVertex2f(x+size, y+size);
                glVertex2f(x-size, y+size);
                glVertex2f(x-size, y-size);
                glVertex2f(x+size, y-size);
        glEnd();
}컬러를 랜덤값으로 받는 모습이다.
/* 새로 추가한 전역변수 */
int random_color = 0;
double r, g, b; // 기존에 있던 전역변수
void drawSquare(int x, int y)
{
    y = wh - y;
    if (random_color == 1)
        glColor3ub((char)rand() % 256, (char)rand() % 256, (char)rand() % 256);
    else glColor3f(r, g, b);
    glBegin(GL_POLYGON);
    glVertex2f(x + size, y + size);
    glVertex2f(x - size, y + size);
    glVertex2f(x - size, y - size);
    glVertex2f(x + size, y - size);
    glEnd();
}새로운 전역변수 random_color를 추가하여 if문으로 분기를 나뉘어서 도트 기능을 확장하였다.
random_color의 값이 1이면 무작위 색의 도트를 찍고 그렇지 않다면 기존에 있던 r,g,b 값으로 색을 초기화 하여 출력한다.
2. 별 그리기 기능

case(STAR):
        {
            rx = x;
            ry = wh - y;
            if(random_color == 0) glColor3f(r, g, b);
            else glColor3ub((char)rand() % 256, (char)rand() % 256, (char)rand() % 256);
            glBegin(GL_POINTS);
            for (double i = 0.0; i < 720; i += 0.1)
                glVertex3f(size * 5 * cos(2 * i) + size * 2.0 * cos(3 * i) + rx, size * 2 * sin(3 * i) - size * 5.0 * sin(2 * i) + ry, 0.0);
            glEnd();
            count = 0;
            break;
        }별 그리기 기능은 다음과 같이 코딩하였다.
switch문의 분기중 하나를 위와같이 발췌하였다.
범위를 지정하는 형식이 아니라 클릭을 하면 별을 그리는 방식으로 구현하였다.
별을 그리는 방법은 극좌표 방정식을 사용하였다.


rx = x;
            ry = wh - y;
            glBegin(GL_POINTS);
            for (int i = 0.0; i < 720; i++)
                glVertex3f(size*5*cos(2*i)+size*2*cos(3*i)+rx, size*2*sin(3*i)-size*5*sin(2*i)+ry, 0.0);
            glEnd();
            draw_mode = 0;
            count = 0;
            
            break;위의 코드의 경우 초기 버전의 별그리기다.
i의 증가량이 1밖에 되지 않아 별의 크기를 늘리자 별의 선이 이어지지 않고 점으로 끊어지는 현상을 발견하였다.
i의 증가량을 0.1로 바꾸어 구현하였더니 첫번째 결과와 같이 선명해지고 선의 끊어짐 현상이 줄어들었다.
3. 브러쉬 기능

void mouseMove(int x, int y) {
    switch (draw_mode) {
    case BRUSH:
            rx = x;
            ry = wh - y;
            glBegin(GL_POLYGON);
            glColor3f(r, g, b);
            for (double i = 0; i < 360; i += 1)
                glVertex2f(size * 5 * cos(i) + rx, size * 5 * sin(i) + ry);
            glEnd();
            break;
	...
브러쉬 기능의 경우 고민을 좀 했다.
원래 고민 했던 방법은
mouse 상태에 따라 마우스 왼쪽이 눌리면 선택한 모드로의 그림이 그려지는 구조인데,
왼쪽이 버튼이 DOWN(눌린)상태에서 UP될때까지 반복문으로 좌표를 받아 드로우 하려고 했으나,
마우스 클릭이 이루어지는 순간만 이벤트로 받아서 그게 잘 안됬다.
그래서 찾아보니 moseMove()라는 함수가 있었다.
마우스가 움직이는 동안 좌표를 계속 보내주는 것이다.
이를 활용하여 움직이는 경로에 원을 계속적으로 그리는 것으로 브러쉬를 구현하였다.

case BRUSH:
        rx = x;
        ry = wh - y;
        glBegin(GL_POINTS);
        glColor3f(r, b, g);
        glVertex2f(rx, ry);
        glEnd();
         
    }
    glPopAttrib();
    glFlush();경로상에 GL_POINTS를 활용하여 점을 계속 찍어보자는 생각을 했는데,
굉장히 얇고 마우스 이동이 빨라지면 완전하게 그려지지 않는다는 점을 활용했다.
따라서 조금 더 큰 사이즈의 원을 마우스 경로에 지속적으로 그리는 방법으로 구현했다.
4. 팔레트 기능 및 윈도우 확장, 기능 추가

이태까지 본 윈도우와 조금 다른 모습을 보일 것이다.
팀 프로젝트로 진행하다 보니 각자의 파트가 있었고, 브러쉬 별 도트 기능 확장까지가 내 파트였다.
이후 지우개와 원 그리기, 배경색 바꾸기가 추가되었는데,
지우개의 경우 브러쉬 컬러를 배경색과 동일하게 맞추어 브러쉬 기능을 하면 되는 것이라 팀원이 구조를 만들고 거기 안에 내가 코딩만 했다.
다만, 팔레트 기능의 경우 설명이 길어질 것 같으니 따로 글을 작성하겠다.
5. 현재 기능 정리

현재 선, 삼각형, 사각형, 점, 문자, 별, 브러쉬(PEN), 지우개, 원 그리기, 팔레트 기능이 구현 되었다.

마우스 우클릭을 할경우 quit, clear 메뉴가 나오고
마우스 휠을 클릭 할 경우 DrawColors, BackgroundColors, OneClickOption, Fill 메뉴가 나오며,
각 하위 메뉴들은 위의 사진과 같다.
6. 정리
생각보다 구현함에 있어서 어려움은 없었다.
특히나 인터넷에 소스코드가 매우 많이 뿌려져 있기 때문에 참고자료가 충분하고,
구현에 있어서 가장 힘들었던 것은 팔레트를 구현하는 것이었다. 이는 다음번에 자세히 다뤄보도록 하겠다.
특이한 점은 gl의 문법이 신기했다는 것이다.
glBegin()의 경우 중괄호로 시작되는 것이 아니라 이 함수가 시작된 시점부터 다음 나오는 vertex들이 모두 그리기에 사용되는 vertex로 취급이 된다. 이후 glEnd()가 호출되면 하나의 도형이 완성되는 것이다.
'Computer Graphics > 그림판 프로그램' 카테고리의 다른 글
| 그림판 프로그램 기능 확장 - 2 : 팔레트 기능 (0) | 2020.11.26 | 
|---|