Window, Viewport Window, Viewport
Device Coordinate Systems, Normalized Coordinate Systems, World Coordinate Systems Device Coordinate: 컴퓨터 화면의 pixel의 위치를 나타내는 고정 좌표 체계. Normalized Coordinate: 출력 장치의 Resolution에 따라서 변화하는 Device 좌표계의 좌표 값의 범위를 0-1사이의 값으로 통일하여 나타내는 좌표 체계. World Coordinate: 나타내려고 하는 사물의 환경에 따라 적절히 설정되는 실 좌표체계. (구현하려는 사물은 World 좌표계 상에서 정의 되지만 컴퓨터 화면에 나타내기 위해서는 결국 Device 좌표계로 바뀌어야 한다) Window, Viewport
Window, Viewport Window: World 좌표계 상에서 실제 화면에 구현하려는 부분을 한정 짓기 위하여 지정되는 영역. (World좌표계의 값을 사용하여 정한다) Viewport: Window 내부의 물체를 화면의 지정된 위치에 mapping하기 위하여 사용하는 화면상의 영역. ( Normalized 좌표 값을 사용하여 정한다) 화면 윈도우 Viewport World 좌표계 Device 좌표계 Window, Viewport
ywmax yw ywmin xw yvmax xwmin xwmax yv yvmin xv xvmin xvmax (xw - xwmin) ywmin xw (xwmax - xwmin) xvmax xvmin yvmin yvmax xv yv xwmin xwmax (xv- xvmin) (xvmax - xvmin) Window, Viewport
Window to Viewport Coordinate Transformation Window 내의 한 점의 위치와 그에 대응하는 Viewport 내의 위치는 다음과 같은 관계가 있다. (xv - xvmin ) / (xvmax - xvmin) = (xw - xwmin) / (xwmax - xwmin) (yv - yvmin ) / (yvmax - yvmin) = (yw - ywmin) / (ywmax - ywmin) 위의 관계로부터 주어진 Window상의 점의 위치에 대응하는 Viewport 내의 좌표(xv, yv)을 구하는 식은 다음과 같다. xv = xvmin + (xw - xwmin) [ (xvmax - xvmin) / (xwmax - xwmin) ] yv = yvmin + (yw - ywmin) [ (yvmax - yvmin) / (ywmax - ywmin) ] 계속 Window, Viewport
앞의 마지막 두 식에서 [ ]안의 상수 term을 다음과 같이 각 각 sx, sy로 대치하면 [ (xvmax - xvmin) / (xwmax - xwmin) ] = sx, [ (yvmax - yvmin) / (ywmax - ywmin) ] = sy 두 식은 다음과 같이 간단히 나타낼 수 있다. xv = xvmin + (xw - xwmin) sx yv = yvmin + (yw - ywmin) sy 이 식을 더욱 간단히 하기 위하여 괄호를 없애고 정리하면 xv = xw . sx + ( xvmin - xwmin . sx) yv = yw . sy + (yvmin - ywmin . sy) 계속 Window, Viewport
xv = xw . sx + cx yv = yw . sy + cy 앞의 마지막 두 식에서 다시 변하지 않는 상수 term (xvmin - xwmin .. sx), (yvmin - ywmin .. sy) 를 각각 cx,cy로 대치하면 두 식은 다음과 같은 형태가 된다. xv = xw . sx + cx yv = yw . sy + cy Window와 Viewport 값에 대하여 sx, sy, cx, cy의 값을 미리 구해 두면 Window 내의 한 점의 위치를 Viewport의 좌표로 구하는 것은 위의 식을 사용하여 간단히 구할 수 있다. sx, sy, cx, cy값은 Window의 크기(위치)와 Viewport의 크기(위치)가 변할 때 마다 다시 계산하여야 한다. 이 계산을 하는 함수가 파일 grinit.c 내의 set_view_constant()이다. 계속 Window, Viewport
static int set_view_constants(void) { if(!graphics_mode) return 0; ViewSx = (XVmax - XVmin) / (XWmax - XWmin); ViewSy = (YVmax - YVmin) / (YWmax - YWmin); ViewCx = XVmin - XWmin * ViewSx; ViewCy = YVmin - YWmin * ViewSy; return 1; } 이 함수는 static함수로서 같은 파일(grinit.c) 내에 있는 다음의 두 함수에서 호출된다. Window, Viewport
Window의 경계를 set하는 함수(grinit.c 파일 내) int set_window(float L, float T, float R, float B) { if(L >= R) return 0; if(B >= T) return 0; XWmin = L; XWmax = R; YWmin = B; YWmax = T; set_view_constants(); return 1; } Window, Viewport
Viewport의 영역을 set하는 함수(grinit.c 파일 내) int set_viewport(float L, float T, float R, float B) { if(L >= R) return 0; if(B >= T) return 0; if(L < 0.0) return 0; if(L > 1.0) return 0; if(R < 0.0) return 0; if(R > 1.0) return 0; if(T < 0.0) return 0; if(T > 1.0) return 0; if(B < 0.0) return 0; if(B > 1.0) return 0; XVmin = L; XVmax = R; YVmin = B; YVmax = T; set_view_constants(); return 1; } Window, Viewport
Window 내의 한 점의 위치를 화면상의 Pixel의 위치(Device Coordinate)로 변환하는 함수(grinit.c 파일 내) int get_pixel_position(float x, float y, int *px, int *py) { *px = round( (x * ViewSx + ViewCx) * MaxPDX ); *py = round(MaxPDY - ( (y * ViewSy + ViewCy) * MaxPDY) ); return 1; } 위의 함수는 Window상의 좌표값을 화면상의 Pixel의 좌표로 변환하여 준다. 식을 자세히 보면 x축의 값은 MaxPDX의 값에 0에서 1사이의 값인 Viewport의 좌표 값이 곱해지는 것을 알 수 있다. 또한 Pixel의 y축의 좌표는 구해진 값을 MaxPDY에서 뺀 값을 사용한다. 그 이유는 화면상의 y축의 좌표 값의 증가 방향과 Window(Viewport)의 좌표 값의 증가 방향이 반대이기 때문이다. Window, Viewport
draw_line()함수 (line.c 파일 내) int draw_line(float x1, float y1, float x2, float y2, float r, float g, float b) { int px1,py1, px2,py2; /* pixel positions */ get_pixel_position(x1,y1, &px1,&py1); get_pixel_position(x2,y2, &px2,&py2); line_bres(px1,py1, px2,py2, r,g,b); return 1; } 이 함수는 추후 line clipping알고리즘 강의 후 약간 변경될 것임 Window, Viewport
case 0: set_viewport(0.0, 1.0, 0.5, 0.5); break; draw_line(-10.0, 10.0, 10.0, -10.0, L_Green); draw_line(-10.0, -10.0, 10.0, 10.0, L_Green); draw_line(-10.0, 10.0, -10.0, -10.0, White); draw_line(-10.0, -10.0, 10.0, -10.0, White); draw_line( 10.0, -10.0, 10.0, 10.0, White); draw_line( 10.0, 10.0, -10.0, 10.0, White); set_video_mode(vga_800x600x64k); set_window(-10.0, 10.0, 10.0, -10.0); set_video_mode(text_80x25x16); int x1,y1, x2,y2, x3,y3, x4,y4, i; /* window and viewport test */ #include "vgainfo.h" for(i=0; i<4; i++) { #include <stdio.h> #include "grinit.h" #include "line.h" void main(void) switch(i) { getch(); } { Window, Viewport, Device 좌표 전환 테스트 프로그램(wintest.c) Window, Viewport