업데이트:

태그:

카테고리:

개요

Fil de Fer라는 의미. 한국어로 철사라는 의미이다. 지도를 제작하는 작은 소프트웨어를 만든다.
구글맵과는 쨉도 안됨….

창을 만들고, 그 안에 픽셀을 그리고, 몇 개의 이벤트를 조작하게된다.

맵파일은 기본적으로 x축, y축을 가진 2차원 평면으로 주어지는데,

x축과 y축은 한 점의 위치이고, z축은 한 점이 가진 값으로 표현된다.

고도를 조정할 수 있고, 줌인 줌아웃, 색변경, 등을 할 수 있다.
또한 창 안에서 그림을 그릴 수도 있다.(점과 점 사이를 잇는다.) 이 알고리즘에 대해선 Bresenham segment를 찾아보자.

여러가지 맵파일. 42맵파일 뿐만아니라, 나라의 지도와 같은 맵 파일을 받아서 이걸로 그릴수도있다.

MinilibX라는 라이브러리는 통칭 MLX라고 불린다.

이에관한 몇가지 man page가 존재한다.


man

1. mlx

mlx => 학생들을 위한 간단한 그래픽 인터페이스 라이브러리.

  • 프로토타입

    #include <mlx.h>
    void *mlx_init ();
    
  • 설명

    MinuLibX는 `X-Window나 Cocoa프로그래핑 지식 없이`그래픽적인 
    소프트웨어를 만들 수 있는 쉬운 방법을 제공한다.  
    간단한 창을 만들 수 있고, 그리기 도구와 이미지, 기본 이벤트 관리를 제공한다.  
    
  • BSD/LINUX에서 X-WINDOW의 이해

    X-Window는 유닉스를 위한 네트워크 지향적 그래픽 시스템이다.  
    X-Window는 2가지의 메인 객체로 구성된다.  
    1. 키보드, 마우스 입력과 스크린에 무언가 그리는 `software`  
    2. 위의 스크린과 키보드, 마우스를 관리하는 `X-Server`. (디스플레이로 통칭)  
    user가 스크린에 그림을 그린다->  
    1. `X-Server`가 키보드, 마우스 이벤트를 스크린 상에서 감지하고, `software`측에 전달한다.  
    2. `software`에서 그리는 명령이 `X-Server`로 전달된다.  
    위 두 객체 사이에 네트워크 연결이 반드시 되어있어야 한다.  
    
  • MACOSX에서 이해

    MacOSX의 운영체제는 스크린, 디스플레이 상으로의 그래픽 접속을 제어한다.  
    한쪽에서는 `software`가 스크린, 마우스, 키보드 객체를 얻고, 스크린 상에 그리는 역할을 한다.  
    다른 쪽에서는 `MacOSX`의 그래픽 프레임워크가 키보드, 마우스, windowing system과 screen을 제어한다.  
    두 객체간 연결이 반드시 만들어져있어야 한다.  
    
  • INCLUDE FILE

    `mlx.h`헤더를 인클루스해야 `MiniLibX` API를 사용할 수 있는데, 이 헤더에는 함수의 프로토타입만 선언되어있다. 
    구조체를 필요로 하지 않는다.  
    
  • LIBRARY FUNCTIONS

    일단, 소프트웨어와 디스플레이 간 연결을 초기화해야한다.  
    연결이 만들어지면, 그래픽적 명령을 보낼 수 있는 `MiniLibX`함수들을 사용할 수 있다.  
    이에는 유저가 키입력을 감지하고, window에 픽셀을 그릴 수 있는 것 등의 명령을 보낼 수 있다.  
    
    `mlx_init`함수가 이 연결을 만드는데, 인자를 필요로하지 않는다.  
    그리고 이 함수는 라이브러리 루틴에 따라 필요되어지는 `void *형태의 식별자를 반환`한다.  
    
    다른 `MiniLibX` 함수의 man page는 밑에서 확인할 수 있다.  
    
    mlx_new_window      : window(창)을 관리
    
    mlx_pixel_put       : window안에 무언가 그림
    
    mlx_new_image       : 이미지를 조작
    
    mlx_loop            : 마우스, 키보드 이벤트를 제어
    
  • BSD/Linux와 X-Window에서 MiniLibX LINKING

    MiniLibX의 함수를 사용하기 위해선, software를 MiniLibX 라이브러리 뿐만아니라 다른 몇몇 라이브러리를 연결해야한다. 
    
    이를 위해선, linking시점에 아래와 같은 인자를 추가하면된다.  
    
    `-lmlx -lXext -lX11`
    
    이 라이브러리들을 위해서 경로를 특정해야할 수 있는데, -L 플래그를 사용한다.
    
  • MACOSX에서 MiniLibX LINKING

    MiniLibX함수를 사용하기 위해선 software를 MiniLibX 라이브러리와 몇개의 시스템 프레임워크를 link해야한다.
      
    `-lmlx -framework OpenGL -framework AppKit`
    
    이 라이브러리들을 위해서 경로를 특정해야할 수 있는데, -L 플래그를 사용한다.
    
  • 반환 값

    mlx_init함수가 그래픽적 시스템과의 연결 설정에 실패하면 `NULL`을 반환하지만, 
    성공하면 연결 식별자로 해당 포인터를 리턴한다.
    



2. mlx_new_window

  • 이름

    MiniLibX - Managing windows
    
  • 함수 프로토타입

    void *mlx_new_window( void *mlx_ptr, int size_x, int size_y, char *title );
    
    int mlx_clear_window ( void *mlx_ptr, void *win_ptr );
    
    int mlx_destroy_window ( void *mlx_ptr, void *win_ptr );
    
  • 설명

    - void *mlx_new_window( void *mlx_ptr, int size_x, int size_y, char *title );  
    
            mlx_new_window()함수는 스크린상에 새로운 window를 생성한다.  
    
            mlx_ptr은 mlx_init()함수가 반환하는 연결 식별자를 사용한다.
    
            인자로 받는 size_x와 size_y를 사용해 크기를 절하며, 제목으로는 title인자를 사용해 표시한다.
    
            mlx_new_window함수는 MiniLibX함수에서 호출되는 다른 함수에 사용될 수 있는 window 식별자를 리턴한다.
            따라서, MiniLibX는 여러 window를 별도로 제어할 수 있다.  
    
    
    - int mlx_clear_window ( void *mlx_ptr, void *win_ptr );  
    - int mlx_destroy_window ( void *mlx_ptr, void *win_ptr );  
    
            mlx_clear_window는 window를 검은 화면으로 초기화해주고,  
            mlx_destroy_window함수는 주어진 window를 없앤다.
    
            두 함수는 동일한 인자를 가지는데, 연결식별자(mlx_ptr)과 window식별자(win_ptr)을 인자로 가진다.
    
  • 반환값

    mlx_new_window함수가 새로운 window를 만드는데에 실패하면 `NULL`을 반환하며, 성공하면 window식별자 포인터를 반환한다.
    mlx_clear_window와 mlx_new_destroy_window는 아무것도 반환하지 않는다.
    



3. mlx_pixel_put

  • 이름

    MiniLibX - Drawing inside windows
    
  • 프로토타입

     int mlx_pixel_put (void *mlx_ptr, void *win_ptr, int x, int y, int color);
    
     int mlx_string_put (void *mlx_ptr, void *win_ptr, int x, int y, int color, char *string);
    
  • 설명

     - int mlx_pixel_put (void *mlx_ptr, void *win_ptr, int x, int y, int color);
       
            mlx_pixel_put()함수는 win_ptr로 접근하는 window안에 정의된 pixel하나를 그린다.  
            이때, 이 픽셀은 x, y로 위치가 지정되고, color로 색을 줄 수 있다.  
            (0,0), 원점은 window상에서 좌상단코너이고, x축과 y축은 우측, 하단방향으로 갈수록 커진다.  
            연결 식별자로 mlx_ptr이 필요하다.
    
    
     - int mlx_string_put (void *mlx_ptr, void *win_ptr, int x, int y, int color, char *string);
    
            mlx_string_put()함수는 위와 같은 인자를 가지지만, 
            픽셀 하나를 그리는게 아니라, (x, y)에 그려질 문자열 하나를 그린다.
            모든 함수에서, 식별자로 전해지는 win_ptr의 
            window바깥이나 선택된 win_ptr외에 다른 window에 그릴 수는 없다.
    
  • 색 관리

     색 인자(color)는 정수형을 가진다.  
    
     표시될 색상은 정의된 방식에 따라 정수형으로 인코딩되어야한다.  
    
     모든 표시가능한 색상은 RGB, Red, Green, Blue의 3가지 기본 색상으로 나뉠 수 있다.  
    
     각각 0 ~ 255범위 (unsigned char)안의 3가지 정수의 조합으로 
     표시되어야하는 색상을 만들기 위해 어떻게 조합되어야하는지 나타낸다.  
    
     이 세 값은 올바른 색상을 표시하기 위해서 정수 범위 내에서 정의되어야한다.  
       
     정수의 최하위 3byte가 아래와 같이 채워진다.  
    
    
             | 0 | R | G | B |   color integer
             +---+---+---+---+
      
     정수를 채울 때, 엔디안 문제에 대해 고려해야한다.
     가장 중요한 것은 blue에 해당하는 바이트가 최하위에 속해야한다는 것이다.  
    



4.mlx_new_image

  • 이름

     MiniLibX - Manipulating images
    
  • 프로토타입

     void *mlx_new_image(void *mlx_ptr, int width, int height);
    
     char *mlx_get_data_addr(void *img_ptr, int *bits_per_pixel, int *size_line, int *endian);
    
     int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y);
    
     unsigned int mlx_get_color_value(void *mlx_ptr, int color);
    
     void *mlx_xpm_to_image(void *mlx_ptr, char **xpm_data, int *width, int *height);
    
     void *mlx_xpm_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
       
     int mlx_destroy_image(void *mlx_ptr, void *img_ptr);
    
  • 설명

     - void *mlx_new_image(void *mlx_ptr, int width, int height);  
    
            mlx_new_image()함수는 메모리 안에 새로운 이미지를 생성한다.  
            이 함수는 나중에 이 이미지를 조작하기위한 식별자를 반환한다.
            mlx_ptr 연결 식별자와, 이미지의 크기를 정의할 width, height인자를 필요로한다.
    
            유저는 이 이미지를 조작할 수 있고(아래 참조), 언제든지 window에 덤프하여 화면에 표시할 수 있다. 
            이 동작은  mlx_put_image_to_window()함수를 통해 이루어진다.
      
    
     - int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y);
    
            여기선 연결 식별자, window 식별자, 그리고 image 식별자가 필요하다.
            그리고 window상에서 image가 어디에 정의되어야하는지 (x, y)좌표가 필요하다.  
    
    
     - char *mlx_get_data_addr(void *img_ptr, int *bits_per_pixel, int *size_line, int *endian);
    
            mlx_get_data_addr()함수는 유저가 조작할 수 있는, 만들어진 이미지에 대한 정보를 리턴해준다.
            img_ptr 인자는 사용할 이미지의 식별자이다.  
    
            나머지 3개의 인자는 3개의 각각 다른 유효한 정수의 주소이다.  
    
            bits_per_pixel인자는 픽셀의 색을 표현하기 위해 필요한 비트 수(이미지의 깊이)를 의미한다.
            size_line는 이미지의 한 줄을 메모리에 저장하는데에 사용되는 바이트의 개수를 의미한다.
            size_line은 이미지 상에서 한 줄에서 다른 줄로 옮겨져야한다.  
            엔디안은 이미지의 픽셀의 색상이 빅 엔디안(endian == 1)아니면 리틀 엔디안(endian == 0)으로 저장되는  
            지를 말해준다.
    
            반환되는 char형 포인터는 이미지가 저장된 메모리 영역의 시작점이다.            
            이 주소로부터 첫 번째 bits_per_pixel의 비트가 이미지의 첫 번째 줄에 있는 첫 번째 픽셀의 색을 표현한다.  
            bits_per_pixel의 두번째 그룹은 이미지의 첫 번째 줄의 두 번째 픽셀을 나타내고, 이런 규칙을 계속 적용해나간다.  
            이미지의 두 번째 줄의 시작점의 주소를 얻기 위해서 size_line을 추가한다.
            이런 방식으로 이미지의 어느 픽셀이든 도달할 수 있다.
    
    
     - int mlx_destroy_image(void *mlx_ptr, void *img_ptr);
    
            mlx_ptr 연결 식별자와 img_ptr 이미지 식별자로 이미지를 삭제한다.      
    
  • 이미지 안에 색을 저장하기

     - unsigned int mlx_get_color_value(void *mlx_ptr, int color);
            
            디스플레이에 따라서, 픽셀의 색을 저장하기위한 비트의 개수는 바뀔 수 있다.
            유저는 RGB로 각각 1바이트를 사용해 색을 표현한다.
            이렇게 표현되는 색상은 이미지가 요구하는 bits_per_pixel에 따라 맞추고, 그래픽 시스템이 그 색상을 이해할 
            수 있도록 번역되어야한다. 
    
            이게 mlx_get_color_value()함수의 목적이다.
    
            이 함수는 RGB색상 인자를 받아서 unsigned int 값을 반환한다.
            이 반환 값의 bits_per_pixel의 최하위 비트들은 이미지에 저장될 수 있다.
    
            컴퓨터의 엔디안 방식에 따라 최하위 비트들이 정렬되는 방식이 달라진다는 것을 명심해야한다.
            실제로, 원격 X11 디스플레이를 위한 X-Server의 컴퓨터의 엔디안 방식이 로컬 컴퓨터의 엔디안과 다르면, 
            사용되기 전에 변환되어야만한다.
    
  • XPM 이미지

     - void *mlx_xpm_to_image(void *mlx_ptr, char **xpm_data, int *width, int *height);
     - void *mlx_xpm_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
              
            The mlx_xpm_to_image()과 mlx_xpm_file_to_image()함수는 같은 방식으로 새로운 이미지를 만든다.
    
            이 함수들은 각각 xpm_data 식별자나 filename 식별자를 사용해 이미지를 채운다.
            MiniLibX는 xpm 이미지를 다루기 위해 표준 Xpm 라이브러리를 사용하지 않는다.  
            일부 유형의 xpm 이미지를 읽을 수 없을수도 있지만, 투명성은 제어한다.  
    
  • RETURN VALUES

     새로운 이미지를 만드는 mlx_new_image(), mlx_xpm_to_image() mlx_xpm_file_to_image()함수는 
     만약 에러가 발생하면 널포인터를 리턴한다.  
     성공하면 이미지 식별자인 포인터를 리턴해준다.
    



5. mlx_loop.1

  • 이름

    MiniLibX - Handle events
    
  • 함수 프로토타입

     int mlx_loop(void *mlx_ptr);
    
     int mlx_key_hook(void *win_ptr, int (*funct_ptr)(), void *param);
    
     int mlx_mouse_hook(void *win_ptr, int (*funct_ptr)(), void *param);
    
     int mlx_expose_hook(void *win_ptr, int (*funct_ptr)(), void *param);
    
     int mlx_loop_hook(void *mlx_ptr, int (*funct_ptr)(), void *param);
    

이벤트

   X-Window와 MacOSX 그래픽 시스템은 양방향이다.
   한쪽에서 프로그램은 픽셀, 이미지를 표시하기위해 스크린에 명령을 보낸다.

   다른 쪽에서는 스크린에 연결된 키보드와 마우스로부터 정보를 받는다.
   이렇게 프로그램이 키보드와 마우스로부터 이벤트를 전달받는다.

DESCRIPTION

   - int mlx_loop(void *mlx_ptr);

          이벤트를 전달받기위해선 mlx_loop()함수를 사용해야한다.
          이 함수는 절대 반환되지 않으며, 이벤트를 기다리는 무한루프를 돌게된다.  
          그리고 이 이벤트와 관련된 사용자 정의 함수를 호출한다.

          연결 식별자인 mlx_ptr만을 인자로 가진다.

          아래 3개의 이벤트에 대해 다른 함수를 할당할 수 있다.

          - 어떤 키가 눌렸는가?
          - 마우스 버튼이 눌렸는가?
          - window상에서 다시 그려져야하는 부분
          (이걸 expose event, 노출 이벤트라고하는데, 이건 작성한 프로그램이 처리해야한다.)

          각 window는 같은 이벤트에 대해 다른 함수를 정의할 수 있다.


   - int mlx_key_hook(void *win_ptr, int (*funct_ptr)(), void *param);
   - int mlx_mouse_hook(void *win_ptr, int (*funct_ptr)(), void *param);
   - int mlx_expose_hook(void *win_ptr, int (*funct_ptr)(), void *param);

          3가지 함수, mlx_key_hook(), mlx_mouse_hook(), mlx_expose_hook() 함수는 동일한 방식으로 동작한다.


          funct_ptr은 이벤트가 발생하면 호출될 함수의 포인터이다.

          이 할당은 win_ptr 식별자로 지정한 창에 한정한다.

          param인자는 함수가 호출될때마다 전달되는데, 필요할수도 있는 매개변수들을 저장되는데에 사용된다.

          
   - int mlx_loop_hook(void *mlx_ptr, int (*funct_ptr)(), void *param);


          mlx_loop_hook 함수의 문법은 위의 함수들과 동일한데, 
		  차이점으로는 funct_ptr이 이벤트가 발생하지 않으면 호출된다는 것이다.
          
          만약에 이벤트를 감지하면, MiniLibX가 고정매개변수를 사용해 해당함수를 호출한다.

          expose_hook(void *param);
          key_hook(int keycode,void *param);
          mouse_hook(int button,int x,int y,void *param);
          loop_hook(void *param);
 
          함수의 이름은 임의로 정할 수 있다.
          위의 4개의 함수는 이벤트에 따라 인자를 구분하기 위해 사용된다.
          위 함수들은 MiniLibX의 부분이 아니다.

   
   - param의 의미
   
          param is the address specified in the mlx_*_hook calls. 
          param은 mlx_*_hook으로 끝나는 함수들이 호출됨에따라 정의된 주소값이다.

          This address is never used nor modified by the MiniLibX. 
          이 주소는 MiniLibX안에서 절대 사용되거나 수정되지 않는다.
          On key and mouse events, additional information is passed:
          키보드나, 마우스 이벤트에서는 추가적인 정보가 전달된다.
           
           1. keycode는 어떤 키가 눌렸는지를 말한다.
              (X11에선 keysymdef.h로 확인, MacOS에선 알아서해라)
           
           2. (x, y)는 마우스가 눌린 위치를 의미한다.
           
           3. button은 마우스의 버튼이 눌렸는지의 여부를 의미한다.
  • 이벤트에서 더 나아가기

     MiniLibX는 모든 유형의 이벤트에 대해 매우 일반적인 접근을 제공한다. 
       
     mlx.h헤더는 mlx_*_hook 함수와 동일한 방식으로 mlx_hook()을 정의한다.
    
     이벤트와 mask값들은 X.h를 포함해 X11로부터 가져온다. MacOSX에서도 동일하다.
    
     mlx_int_param_event.c의 소스코드를 보면 
     MiniLibX가 어떻게 특정 이벤트에 대해 함수를 호출하는지에 대해 알 수 있다.
    



여기까지 mlx의 man page이다.
이번엔 각 함수가 어떻게 동작하는지 확인해야한다.



#include "mlx.h"

int main()
{
       void   *mlx_ptr;
       void   *win_ptr;

       mlx_ptr = mlx_init(); 
       //mlx_init은 mlx_ptr 연결 식별자를 반환.
       
       win_ptr = mlx_new_window(mlx_ptr, 500, 500, "mlx test"); 
       //mlx_new_window는 mlx_ptr연결 식별자를 통해 매개변수로 
	   window 크기, 제목을 받아 window 식별자를 리턴한다.
       
       mlx_pixel_put(mlx_ptr, win_ptr, 250, 250, 0xFFFFFF);
       //연결식별자와 윈도우식별자로 인자로 받은 위치에 특정 색의 픽셀을 표시한다.
       
       mlx_key_hook(win_ptr, desl_key, (void *)0);
       //키를 입력받으면 가운데 함수를 통해 param으로 키의 정보가 들어가게된다.

       mlx_loop(mlx_ptr);
       //mlx_loop함수가 mlx_ptr과 연결에 대해서 이벤트를 계속 감지한다.
}

댓글남기기