FDF(1)
개요
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과 연결에 대해서 이벤트를 계속 감지한다.
}
댓글남기기