#keywords 그래픽,좌표계,pixel,bound,coords,x,y,screen,frame,buffer,layer #title 그래픽 좌표계 [wiki:Home 대문] / [wiki:CategoryProgramming 프로그래밍] / [wiki:GraphicsCoordsSystem 그래픽 좌표계] ---- == [wiki:GraphicsCoordsSystem 그래픽 좌표계] == * 작성자 조재혁([mailto:minzkn@minzkn.com]) * 고친과정 2010년 3월 20일 : 처음씀 [[TableOfContents]] === 좌표계의 종류 === [[Play(https://youtu.be/Ci4it99elTE)]] [[Play(https://youtu.be/BsGZthivbBY)]] [attachment:coords_system.png] 위 그림은 아래 설명을 위해서 작성한 하나의 가상 화면입니다. * 하나의 점은 16K color 수를 표현할수 있다고 가정합니다. * 흰색(White) 부분이 실제 모니터에 표시되는 점이며 검은색이 비 가시영역으로 볼수 있습니다. 모니터를 자세히 들여다 보세요. 점의 집합으로 표현되는 이러한 화면에서 좌표계의 선택은 매우 중요한 요소입니다. * 파란색(Blue) 사각형 하나는 실제 화면에 표시되는 점을 기준으로 하는 좌표계를 가정합니다. (Pixel 좌표계) * 초록색(Green) 사각형은 실제 화면에 보이지 않는 비가시영역을 기준으로 하는 좌표계를 가정합니다. ( Bound 좌표계: 이 영역은 Paging unit의 효율을 위해서 하나의 Row당 Padding되는 영역으로 설명될수 있습니다. ) * 이와 같이 실제 표시되는 점을 기준으로 하는 좌표표현 방법(Pixel 좌표계)과 표시되는 점의 외곽의 비가시영역을 기준으로 하는 좌표표현 방법(Bound 좌표계)이 존재합니다. 어느것이 더 좋다고 하는 것 보다는 자신의 그래픽 구현이 어느것에 더 유리한지 고민후에 좌표계를 결정하는 개발자의 판단 몫이라고 할수 있겠습니다. === Pixel 좌표계 === 실제 화면에 표시되는 점을 하나의 단위로 보는 좌표계입니다. 위에서 화면전체는 Pixel좌표계로는 다음과 같이 표시될수 있습니다. {{{#!enscript c typedef struct hwport_rectangle_ts { int x, y; unsigned int width, height; }__hwport_rectangle_t; #define hwport_rectangle_t __hwport_rectangle_t typedef struct hwport_screen_ts { int bits_per_pixel; size_t bytes_per_line; hwport_rectangle_t rectangle; }__hwport_screen_t; #define hwport_screen_t __hwport_screen_t static hwport_screen_t my_screen = { 16, /* bits_per_pixel = <위 그림에서 하나의 점은 16K 의 Color수를 표현한다고 가정하면 하나의 점을 표현하는데는 16bits가 필요합니다.> */ (size_t)((32u + 4u) * (16u / 8u)), /* bytes_per_line = 가시영역인 32개의 가로 Pixel수와 비가시영역 4개의 Pixel을 더하고 bits_per_pixel을 bytes_per_pixel로 곱한것입니다. */ { 0, 0, 32u, 32u } /* rectangle = 비가시영역을 제외한 부분을 뜻합니다. 여기서 x, y는 항상 0이라고 할수는 없고 Over scan등이 고려될때는 0이 아닐수 있습니다. */ }; }}} 위의 그림에서 붉은색 사각형은 다음과 같이 표현될수 있습니다. {{{#!enscript c hwport_rectangle_t my_rectangle = { 2, 2, 9u, 9u }; }}} 또 다른 표현으로는 다음과 같이도 표현합니다. {{{#!enscript c typedef struct hwport_region_ts { int x1, y1, x2, y2; }__hwport_region_t; #define hwport_region_t __hwport_region_t hwport_region_t my_region = { 2, 2, 10, 10 }; }}} 만약 hwport_region_t 를 hwport_rectangle_t 로 변환하려면 다음과 같은 공식이 성립합니다. {{{#!enscript c #define MIN(m_left,m_right) ((m_left < m_right) ? (m_left) : (m_right)) #define MAX(m_left,m_right) ((m_left > m_right) ? (m_left) : (m_right)) my_rectangle.x = MIN(my_region.x1, my_region.x2); my_rectangle.y = MIN(my_region.y1, my_region.y2); my_rectangle.width = (unsigned int)( MAX(my_region.x1, my_region.x2) - MIN(my_region.x1, my_region.x2) + 1 ); my_rectangle.height = (unsigned int)( MAX(my_region.y1, my_region.y2) - MIN(my_region.y1, my_region.y2) + 1 ); }}} 반대로 hwport_rectangle_t 를 hwport_region_t 로 변환하려면 다음과 같은 공식이 성립합니다. {{{#!enscript c if((my_rectangle.width <= 0u) || (my_rectangle.height <= 0u)) { /* ERROR: invalid width or height */ } my_region.x1 = my_rectangle.x; my_region.y1 = my_rectangle.y; my_region.x2 = ((int)my_rectangle.width) - my_rectangle.x - 1; my_region.y2 = ((int)my_rectangle.height) - my_rectangle.y - 1; }}} === Bound(Screen) 좌표계 === 하나의 점 마저도 크게 확대해보면 사각형 또는 어느 범위안의 구역이라는 시점으로 바라본 좌표계로써 보이는 점들의 외곽영역을 기준으로 하는 좌표계 {{{#!enscript c typedef struct hwport_bound_ts { int left, top, right, bottom; }__hwport_bound_t; #define hwport_bound_t __hwport_bound_t typedef struct hwport_screen_ts { int bits_per_pixel; size_t bytes_per_line; hwport_bound_t bound; }__hwport_screen_t; #define hwport_screen_t __hwport_screen_t static hwport_screen_t my_screen = { 16, /* bits_per_pixel */ (32 + 4) * (16 / 8), /* bytes_per_line */ { 0, 0, 32, 32 } /* bound */ }; }}} 위의 그림에서 붉은색 사각형은 다음과 같이 표현될수 있습니다. {{{#!enscript c hwport_bound_t my_bound = { 2, 2, 11, 11 }; }}} === Pixel 좌표계와 Bound 좌표계의 분석 === hwport_bound_t를 hwport_rectangle_t 로 변환하려면 다음과 같은 공식이 성립합니다. hwport_region_t를 hwport_rectangle_t 로 변환할때는 1을 더해주어야 했다는 점이 주목해야 될 부분입니다. {{{#!enscript c my_rectangle.x = my_bound.left; my_rectangle.y = my_bound.top; my_rectangle.width = (unsigned int)(my_bound.right - my_bound.left); my_rectangle.height = (unsigned int)(my_bound.bottom - my_bound.top); }}} === 2개의 window(Pixel 좌표계 기준) 가 겹치는 영역을 계산하는 예제 === 이 예제는 2개의 Window 사각 영역에 대하여 겹쳐지는 영역과 겹쳐지지 않는 영역을 계산하는 예제입니다. 보통 Windows Manager 개발에 필요한 요소로 볼 수 있으며 겹쳐지지 않는 영역은 완벽하게 식별하기 위해서는 4개의 영역으로 나뉘어 다룰수 있습니다. 실제 이 연산을 기반으로 Windows Manager를 개발하게 되면 재귀적 연산부가 심도있게 다루어져야 하는데 통상 재귀적 Stack 이용률이 매우 크기 때문에 재귀적인 부분을 비 재귀적 연산으로 개발하는 고려가 되어야 바람직합니다. {{{#!enscript c /* ************************ *[deal] | * * (0) | * * | * *------********** * * *[other] * (1) * * * * * * *Overlap * * * (3) * * * * * * * * **********------* * | * * | (2) * * | * ************************ */ #if !defined(hwport_rectangle_t) # pragma pack(push,8) typedef struct hwport_rectangle_ts { int m_x; int m_y; unsigned int m_w; unsigned int m_h; }__hwport_rectangle_t; # pragma pack(pop) # define hwport_rectangle_t __hwport_rectangle_t #endif int hwport_sep_overlap_window(const hwport_rectangle_t *s_deal_region, const hwport_rectangle_t *s_other_region, hwport_rectangle_t *s_overlap_region, hwport_rectangle_t *s_no_overlap_region /* array[4] */) { int s_temp1; int s_temp2; hwport_rectangle_t s_temp_window; if(hwport_unlikely((s_deal_region == ((hwport_rectangle_t *)0)) || (s_other_region == ((hwport_rectangle_t *)0)))) { return(-1); } /* wide region select to s_temp_window */ s_temp_window.m_x = (s_deal_region->m_x <= s_other_region->m_x) ? s_deal_region->m_x : s_other_region->m_x; s_temp_window.m_y = (s_deal_region->m_y <= s_other_region->m_y) ? s_deal_region->m_y : s_other_region->m_y; s_temp1 = s_deal_region->m_x + ((int)s_deal_region->m_w); s_temp2 = s_other_region->m_x + ((int)s_other_region->m_w); if(s_temp2 > s_temp1) { s_temp1 = s_temp2; } s_temp_window.m_w = (unsigned int)(s_temp1 - s_temp_window.m_x); s_temp1 = s_deal_region->m_y + ((int)s_deal_region->m_h); s_temp2 = s_other_region->m_y + ((int)s_other_region->m_h); if(s_temp2 > s_temp1) { s_temp1 = s_temp2; } s_temp_window.m_h = (unsigned int)(s_temp1 - s_temp_window.m_y); if(((s_deal_region->m_w + s_other_region->m_w) <= s_temp_window.m_w) || ((s_deal_region->m_h + s_other_region->m_h) <= s_temp_window.m_h)) { /* no overlap */ return(0); } if(s_overlap_region == ((hwport_rectangle_t *)0)) { s_overlap_region = (hwport_rectangle_t *)(&s_temp_window); } /* overlap region select */ s_overlap_region->m_x = (s_deal_region->m_x >= s_other_region->m_x) ? s_deal_region->m_x : s_other_region->m_x; s_overlap_region->m_y = (s_deal_region->m_y >= s_other_region->m_y) ? s_deal_region->m_y : s_other_region->m_y; s_overlap_region->m_w = s_deal_region->m_w + s_other_region->m_w - s_temp_window.m_w; s_overlap_region->m_h = s_deal_region->m_h + s_other_region->m_h - s_temp_window.m_h; /* no overlap region select */ if(s_no_overlap_region != ((hwport_rectangle_t *)0)) { s_no_overlap_region[0].m_x = s_deal_region->m_x; s_no_overlap_region[0].m_y = s_deal_region->m_y; s_no_overlap_region[0].m_w = (unsigned int)(s_overlap_region->m_x + ((int)s_overlap_region->m_w) - s_deal_region->m_x); s_no_overlap_region[0].m_h = (unsigned int)(s_overlap_region->m_y - s_deal_region->m_y); s_no_overlap_region[1].m_x = s_overlap_region->m_x + ((int)s_overlap_region->m_w); s_no_overlap_region[1].m_y = s_deal_region->m_y; s_no_overlap_region[1].m_w = (unsigned int)((s_deal_region->m_x + ((int)s_deal_region->m_w)) - (s_overlap_region->m_x + ((int)s_overlap_region->m_w))); s_no_overlap_region[1].m_h = (unsigned int)((s_overlap_region->m_y + ((int)s_overlap_region->m_h)) - s_deal_region->m_y); s_no_overlap_region[2].m_x = s_overlap_region->m_x; s_no_overlap_region[2].m_y = s_overlap_region->m_y + ((int)s_overlap_region->m_h); s_no_overlap_region[2].m_w = (unsigned int)(((int)s_deal_region->m_w) - (s_overlap_region->m_x - s_deal_region->m_x)); s_no_overlap_region[2].m_h = (unsigned int)((s_deal_region->m_y + ((int)s_deal_region->m_h)) - (s_overlap_region->m_y + ((int)s_overlap_region->m_h))); s_no_overlap_region[3].m_x = s_deal_region->m_x; s_no_overlap_region[3].m_y = s_overlap_region->m_y; s_no_overlap_region[3].m_w = (unsigned int)(s_overlap_region->m_x - s_deal_region->m_x); s_no_overlap_region[3].m_h = (unsigned int)(((int)s_deal_region->m_h) - (s_overlap_region->m_y - s_deal_region->m_y)); } return(1); } }}} === 예제소스 === * [attachment:bitblit.tar.gz] : Text console 상에서 구현하는 간략한 FrameBuffer 에 대한 개념을 이해하기 위한 예제 * [attachment:fbinfo.tar.gz] : Linux Frame Buffer 를 이해하기 위한 간략한 FrameBuffer 정보추출 기초 예제 * [attachment:fbclock.tar.gz] : Linux Frame Buffer 상에서 시계바늘을 그리는 간략한 예제 (점, 선, 회전각에 대한 이해를 위한...) * [attachment:fbfire.tar.gz] : Linux Frame Buffer 상에서 좀더 가시적인 효과를 어떻게 구현하는지에 대한 예제 (불타오르는 화면효과 연출, 색상을 다루는 예제) * [attachment:CompositeHangul/bitmap.tar.gz] : Text console 상에서 간략히 글자를 어떻게 Bitmap으로 다루고 이를 Frame Buffer에 도입할수 있는지에 대한 예제 * [attachment:3DGraphics/mz3d.tar.gz] : Linux frame buffer 상에서 동작하는 3차원를 다루는 예제 * [attachment:3DGraphics/mz3dx_simple.tar.gz] : X-Windows 상에서 동작하는 3차원을 다루는 예제