Digital 3D Anthropometry 5. 3D View Class Sungmin Kim SEOUL NATIONAL UNIVERSITY 3D View Class ์์ค๊ณ 3 ์ฐจ์๊ทธ๋ํฝ์๊ฐ์ Introduction Surface graphics Volume graphics Lighting and shading 3์ฐจ์๋ชจ๋ธ์ 2์ฐจ์ํ๋ฉด์ํ์ํ๋ํด๋์ค Rendering Context ๋ง๋ค๊ธฐ ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ ์์ ๋ณํ 2
Surface Graphics Polygonal Mesh ๋ฅผ์ด์ฉํด์๋ฌผ์ฒด์ํ๋ฉด๋ง์๊ทธ๋ฆฌ๋๋ฐฉ๋ฒ ์ฅ๋ฉด์๋ณต์ก์ฑ์๋ฐ๋ผ์ฒ๋ฆฌ์๋๊ฐ๋ฌ๋ผ์ง ํ๋์จ์ด๊ฐ์์ด์ฉ์ดํจ ๋๋ถ๋ถ์๊ทธ๋ํฝ์ดํ๋ฆฌ์ผ์ด์ ์์ฌ์ฉ๋จ Computer Graphics 3 Surface Graphics ๋ฉ์ฌ (Mesh) ๊ตฌ์กฐ๋ชจ๋ธ๋ง ์ฃผ๋ก์ผ๊ฐํ mesh ๊ฐ์ฌ์ฉ๋จ vertex, edge, face ๋ก๊ตฌ์ฑ Computer Graphics face normal vector 4
Volume Graphics ๋ณต์ (Voxel, Volume Element) ๊ธฐ๋ฐ์๋ชจ๋ธ๋ง ์ฅ๋ฉด์๋ณต์ก๋์๊ด๊ณ์์ด์ผ์ ํ์ฒ๋ฆฌ์๋๋ฅผ๊ฐ์ง ํ๋ฆฝ๋ํ๋์จ์ด๊ฐ์๋ฐฉ๋ฒ์ด์์ Compositing ํ๋ก์ธ์ค์๋ณต์ก์ฑ์๊ธฐ์ธ ์ํ๋ถ์ผ๋ฑ์์ฌ์ฉ Computer Graphics 5 ์กฐ๋ช ์ค์์ฑ ์ฅ๋ฉด์์ฌ์ค์ฑ์๋์ฌ์ค ์ด๋ ค์ ๋ค์ํ๊ด์์ํจ๊ณผ ์ผ๊ด, ๋ถ, ์ ๊ตฌ๋ฑ ๋ฌผ์ฒด์ํ๋ฉด์ฑ์ง๊ณผ์์์ํจ๊ณผ ๋ฐ์ง์ด๋ํ๋ฉด, ๊ฑฐ์นํ๋ฉด๋ฑ Lighting Directional (Parallel) Spot (Specular) Point Ambient (Incident) 6
์ ์ ๋น์๋ฐ์ฌ๋ฅผ๊ณ ๋ คํ์์์๊ณ์ฐ Shading ์ข ๋ฅ ๋ฌผ์ฒด์mesh ์๊ฐ์ ์๋ํด๊ณ์ฐ Mesh ๋ด๋ถ์์ ๋ค์๋ํด interpolation Flat shading Gouraud shading Phong shading Face normal vector Light Angle Triangular Element Flat Shading 7 Gouraud Shading Mesh ์๊ฐ๊ผญ์ง์ ์๋ํด๊ณ์ฐ Shading Barycentric Coordinate ๋ฅผ์จ์ interpolation c2 c3 a1 C a2 a3 c1 c1 a1 c2 a2 c3 a3 C a1 a2 a3 Barycentric Coordinate System 8
Phong Shading Mesh ๊ผญ์ง์ ์ normal vector ๋ฅผ interpolation Shading Interpolated normal ์์ด์ฉํ shading Specular Light ์์ํ highlight ์ด๊ตฌํ๋จ Interpolated Normal vector 9 Global Illumination ๊ดํํ์์์ถฉ์คํ๋ฌ์ฌํ๋ ๋๋ง์ผ๋ก๋งค์ฐ์ฌ์ค์ ์ธํํ์ด๊ฐ๋ฅํจ ๋ฐ์ฌ, ๊ตด์ , ํฌ๋ช ๋, ๊ทธ๋ฆผ์๋ฑ์ํํ ์์ฒญ๋๊ณ์ฐ์ดํ์ํจ Rendering 10
์ค์์ฑ ๋ฌผ์ฒด์๋ณต์ก๋๋ฅผ๋์ด์ง์๊ณ ์ฌ์ค์ฑ์ํฅ์ํ ์์๋๋ฐฉ๋ฒ ๋ฐฉ๋ฒ ๋ฌผ์ฒด์ํ์์๋ง๋ 2D ์ด๋ฏธ์ง๋ฅผ์์ฑ ๋ฉ์ฌ์๊ผญ์ง์ ์ํ ์ค์ณ์ขํ๋ฅผ์ค์ Texture Mapping 11 OpenGL (Open Graphics Library) ์์ญ์ฌ 1992 ๋ ์ค๋ฆฌ์ฝ๊ทธ๋ํฝ์ค์ฌ์์๋ง๋ 2 ์ฐจ์๋ฐ 3 ์ฐจ์๊ทธ๋ํฝ์คํ์ค๊ท๊ฒฉ OpenGL 1980 ๋ ๋์๋ค์ํ๊ทธ๋ํฝํ๋์จ์ด์๋ง๋์ํํธ์จ์ด๋ฅผ๊ฐ๋ฐํ๋์ผ์๋งค์ฐ์ด๋ ค์ ์ ์ํํธ์จ์ด๊ฐ๋ฐ์๋ค์ด๊ฐ๋ณํ๋์จ์ด์๋ง์ถ์ด๋ง์ถค์์ธํฐํ์ด์ค์๋๋ผ์ด๋ฒ๋ฅผ์์ฑ ์ค๋ฆฌ์ฝ๊ทธ๋ํฝ์ค (SGI) IrisGL API (Application Programming Interface) ๋ฅผ์คํ์์ค๋ก์ ํ ํ๋ก๊ทธ๋๋ฐ์ธ์ด๊ฐ, ํ๋ซํผ๊ฐ์๊ต์ฐจ์์ฉํ๋ก๊ทธ๋๋ฐ์์ง์ ๋ง์ดํฌ๋ก์ํํธ์ฌ์ Direct3D ์ํจ๊ป์ปดํจํฐ๊ทธ๋ํฝ์ธ๊ณ๋ฅผ์๋ถ ํ์ค์์ด์ฌ๋ฌ๊ด๋ จ์ ์ฒด์ํ ๋ก ๊ณผ์ ์์ผ๋ก์ด๋ฃจ์ด์ง๊ธฐ์๋ฒ์ ์ ๋ฐ์ดํธ๋๋๋ฆฐํธ์ด๋ค ๋น์๋ฆฌ๊ธฐ์ ์ปจ์์์์ธํฌ๋ก๋ ธ์ค๊ทธ๋ฃน์์ํ์ฌ๊ด๋ฆฌ๋๊ณ ์๋ค ์ฝ 250 ์ฌ๊ฐ์ API ํจ์ํธ์ถ์์ด์ฉ ํน์ง ๋จ์ํ๊ธฐํ๋ํ์์๋ถํฐ๋ณต์กํ์ผ์ฐจ์์ฅ๋ฉด๊น์ง์์ฑ๊ฐ๋ฅ ๊ฒ์, CAD, ๊ฐ์ํ์ค, ์ ๋ณด์๊ฐํ, ๋นํ์๋ฎฌ๋ ์ด์ ๋ฑ์๋ถ์ผ์์ํ์ฉ ์๋ก๋ค๋ฅธํ๋์จ์ด์๋ํด๋จ์ผํ API ๋ฅผ์ ๊ณต ํ๋์จ์ดํ๋ซํผ์๋ฅ๋ ฅ์ฐจ์ด๋ฅผ๋ณด์ํจ 12
OpenGL ์ํ์ฅ OpenGL GLSL GLUT SDL GLU GLee GLEW GLUI GLFW GLM SFML GLUX OpenGL์์์๋ ๋ฒจ์ ฐ์ด๋ฉ์ธ์ด์๋์์คํ ์๋ ๋ฆฝ์ ์ธ OpenGL ํ๋ก๊ทธ๋จ์์์ฑํ๋๋ก๋์์ฃผ๋๋๊ตฌ Simple DirectMedia Layer OpenGL ํ๋ก๊ทธ๋จ์์ํ์ถ๊ฐ์ ์ธํจ์๋ฅผ์ ๊ณต OpenGL ํ๋ก๊ทธ๋จ์์ํ๋จ์ํ์ถ๊ฐ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ณต OpenGL ํ์ฅ Wrangler ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ณต GLUT๋ก๋ง๋ค์ด์ง GUI ํดํท์ผ๋ก๋ฒํผ, ์ฒดํฌ๋ฐ์ค๋ฑ์ GUI ๊ธฐ๋ฅ์์ ๊ณต OpenGL ์์ฉํ๋ก๊ทธ๋จ๊ฐ๋ฐ์์ํ์ด์๊ฐ๋ฅํํ๋ ์์ํฌ GLSL ๊ท๊ฒฉ์๊ธฐ๋ฐํ OpenGL์์ํ C++ ์ํํดํท๊ฐ๋จํ๊ณ ๋น ๋ฅธ๋ฉํฐ๋ฏธ๋์ด๋ผ์ด๋ธ๋ฌ๋ฆฌ OpenGL ์ ํธ๋ฆฌํฐ๋ฐ๋ณด์กฐ๋ผ์ด๋ธ๋ฌ๋ฆฌ 13 C++ Builder ์์ OpenGL ์์๋์์ ํ๋ฉด๋ฒํผ์๊ฐ์์์ฑ์ Rendering Context ์์ฑ OnCreate, OnResize ์ฅ๋ฉด์์ ์ค์ ๋ฑ๊ทธ๋ฆฌ๊ธฐ์ค๋น์์ OnPaint Rendering Context ์์ฅ๋ฉด์๊ทธ๋ฆฌ๊ธฐ OnPaint Rendering Context ์ํ๋ฉด๋ฒํผ๋ฅผ์๋ก๋ฐ๊พธ๊ธฐ OnPaint Rendering Context ๋ฅผ์ญ์ OnClose 14
OpenGL ์๊ธฐ์ด Rendering Context ๋ง๋ค๊ธฐ ํ๋ฉด๊ณผํธํ๋๋ Pixel Format ์์ ํ๋ฐ์ด๋ฅผ๋ฐํ์ผ๋กํ Rendering Context ์ค์ DWORD dwflags=pfd_draw_to_window PFD_SUPPORT_OPENGL PFD_DOUBLEBUFFER; PIXELFORMATDESCRIPTOR pfd= sizeof(pixelformatdescriptor), 1, dwflags, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0,0, 0,0,0,0,0, 24, 0, 0, PFD_MAIN_PLANE, 0, 0,0, ; PixelFormat = ChoosePixelFormat(DC, &pfd); if (PixelFormat) SetPixelFormat(DC, PixelFormat, &pfd); RC=wglCreateContext(DC); 15 OpenGL ์๊ธฐ์ด ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ์ค๋น ํ๋ฉด์ํฌ๊ธฐ์์ข ํก๋น๋ฑ์๊ฒฐ์ ํ๊ธฐ height XRes=GetDeviceCaps(DC,LOGPIXELSX); YRes=GetDeviceCaps(DC,LOGPIXELSY); AspectRatio=((GLfloat)Width*(GLfloat)YRes)/((GLfloat)Height*(GLfloat)XRes); (left,bottom) width 16
OpenGL ์๊ธฐ์ด ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ์์ ๋ฐฐ๊ฒฝ์ง์ฐ๊ธฐ Depth buffer์ด๊ธฐํ ์กฐ๋ช ๋ฐ์ฌ์ง์ค์ wglmakecurrent(dc,rc); glcleardepth(1); glenable(gl_depth_test); gldepthfunc(gl_lequal); glhint(gl_perspective_correction_hint, GL_NICEST); glclearaccum(0,0,0,0); gldisable(gl_cull_face); glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT GL_ACCUM_BUFFER_BIT); glenable( GL_COLOR_MATERIAL); glenable(gl_lighting); glenable(gl_light0); 17 OpenGL ์๊ธฐ์ด ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ์์ ์์ ๋ฐ๋ชจ๋ธํ์๋ฐฉ๋ฒ๊ฒฐ์ ํ๋ ฌ์์ด์ฉํ์์ฐจ์ ๋ณํ๋๋๋ช ์์ ์ธ์ง์ glmatrixmode(gl_projection); glloadidentity(); gluperspective(60.0f,aspectratio,1,10000); glmatrixmode(gl_modelview); glloadidentity(); glulookat(0,0,100,,0,0,0,0,1,0); // eye point, scene center, up vector 18
OpenGL ์๊ธฐ์ด ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ์ข ๋ฃ Rendering Context ์ํ๋ฉด Buffer ๋ฅผ๋ฐ๊พธ๊ธฐ Flicker ๋ฐฉ์ง glflush(); SwapBuffers(DC); wglmakecurrent(dc,null); OpenGL ์ธ์ ์ข ๋ฃ wglmakecurrent(dc,0); if (RC) wgldeletecontext(rc); 19 Class ์ค๊ณ C++ Builder ์๋ฌธ์ OnCreate, OnResize, OnPaint Event ์์ Device Context ๊ฐ๋ณํ ์์๋ค #include #include #include #include <vcl.h> <gl/gl.h> <gl/glu.h> "TPoint3D.h" class public : (HDC,int,int,int,int); ~(); HDC LastDC; HGLRC RC; ; int int float void void void PixelFormat; Left,Bottom,Width,Height,XRes,YRes; AspectRatio; CreateRenderingContext(HDC); BeginDraw(HDC); EndDraw(HDC); 20
Class ์ค๊ณ ์์ฑ์์ํ๊ดด์ ::(HDC DC,int l,int b,int r,int t) CreateRenderingContext(DC); // Rendering Context ๋ง๋ค๊ธฐ Left=l; Bottom=b; Width=r-l; Height=t-b; XRes=GetDeviceCaps(DC,LOGPIXELSX); // ํด๋น Device context ์ํด์๋๊ตฌํ๊ธฐ YRes=GetDeviceCaps(DC,LOGPIXELSY); AspectRatio=((GLfloat)Width*(GLfloat)YRes)/((GLfloat)Height*(GLfloat)XRes); ::~() wglmakecurrent(lastdc,0); if (RC) wgldeletecontext(rc); RC=0; // ์ต์ข ์ ์ผ๋ก์ฌ์ฉ๋ DC ๋ฅผ์ด์ฉ 21 Class ์ค๊ณ CreateRenderingContext ํจ์ void ::CreateRenderingContext(HDC DC) DWORD dwflags=pfd_draw_to_window PFD_SUPPORT_OPENGL PFD_DOUBLEBUFFER; PIXELFORMATDESCRIPTOR pfd= sizeof(pixelformatdescriptor), 1, dwflags, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0,0, 0,0,0,0,0, 24, 0, 0, PFD_MAIN_PLANE, 0, 0,0, ; PixelFormat = ChoosePixelFormat(DC, &pfd); if (PixelFormat) SetPixelFormat(DC, PixelFormat, &pfd); RC=wglCreateContext(DC); 22
Class ์ค๊ณ ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ์ค๋น void ::BeginDraw(HDC DC) if (!RC) return; wglmakecurrent(dc,rc); glcleardepth(1); glenable(gl_depth_test); gldepthfunc(gl_lequal); glhint(gl_perspective_correction_hint, GL_NICEST); glclearaccum(0,0,0,0); gldisable(gl_cull_face); glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT GL_ACCUM_BUFFER_BIT); glenable(gl_color_material); glenable(gl_lighting); glenable(gl_light0); glmatrixmode(gl_projection); glloadidentity(); gluperspective(60.0f,aspectratio,1,10000); glmatrixmode(gl_modelview); glloadidentity(); glulookat(0,0,100,0,0,0,0,1,0); // eye/center/up 23 Class ์ค๊ณ ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ์ข ๋ฃ void ::EndDraw(HDC DC) LastDC=DC; // ์ต์ข ์ ์ผ๋ก์ฌ์ฉํ DC๋ฅผ๊ธฐ๋ก glflush(); SwapBuffers(DC); wglmakecurrent(dc,null); 24
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์ํ๋ก์ ํธ์์ SDI ํ๋ก๊ทธ๋จ์์์ฑ TMainForm ์์์ฑ์ / ํ๊ดด์ #include ".h"... class TMainForm : public TForm... ; *GL; fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) GL=0; void fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) if (GL) delete GL; GL=0; Action=caFree; 25 ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ํด๋์ค์ด๊ธฐํ OnCreate, OnResize event handler ์์ฑ void fastcall TMainForm::FormCreate(TObject *Sender) GL=new (Canvas->Handle,0,0,ClientWidth,ClientHeight); void fastcall TMainForm::FormResize(TObject *Sender) if (GL) delete GL; GL=new (Canvas->Handle,0,0,ClientWidth,ClientHeight); FormPaint(this); 26
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์ฅ๋ฉด๊ทธ๋ฆฌ๊ธฐ OnPaint event handler ์์ฑ void fastcall TMainForm::FormPaint(TObject *Sender) if (GL) GL->BeginDraw(Canvas->Handle); glbegin(gl_triangles); glcolor3f(1,0,0); glnormal3f(0,0,1); glvertex3f(-10,-10,0); glvertex3f(10,-10,0); glvertex3f(0,10,0); glend(); GL->EndDraw(Canvas->Handle); 27 ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ๋ณํ๊ธฐ๋ฅ ํ์ ์ด๋ EyePoint ์ UpVector ๋ฅผ์กฐ์ ํ๋์ถ์ Scene Center ์ EyePoint ๊ฑฐ๋ฆฌ์กฐ์ Scene Center ์ EyePoint ์์น์ด๋ Up Vector Eye Point Scene Center 28
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ Mouse Event Handler ์ ์ ํด๋์ค์ mouse event handler ํจ์๋ฅผ์ ์ void fastcall TMainForm::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) if (GL) GL->MouseDown(Button,Shift,X,Y); void fastcall TMainForm::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) if (GL) if (GL->MouseMove(Shift,X,Y)) FormPaint(this); void fastcall TMainForm::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) if (GL) GL->MouseUp(Button,Shift,X,Y); 29 ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ๋ณ๊ฒฝ์ํ์ํ๋ณ์๋ฐํจ์์ค์ bool DragStart; TPoint3D O_SceneCenter,O_EyePoint,O_UpVector; // ์ด๊ธฐ viewport TPoint2D Rotation,Start; // ํ์ ๋, ๋ง์ฐ์ค์์์ void CalculateViewport); // ์์ ๊ณ์ฐํจ์ void bool void MouseDown(TMouseButton Button,TShiftState Shift, int X, int Y); MouseMove(TShiftState Shift,int X, int Y); MouseUp(TMouseButton Button,TShiftState Shift, int X, int Y); ::(HDC DC,int l,int b,int r,int t)... O_SceneCenter.Set(0,0,0); O_EyePoint.Set(0,0,100); O_UpVector.Set(0,1,0); Rotation.Set(0,0); CalculateViewport(); DragStart=false; 30
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ํ์ void ::MouseDown(TMouseButton Button,TShiftState Shift, int X, int Y) if (!DragStart) DragStart=true; Start.Set(X,Y); // ๋ง์ฐ์ค์์์ bool ::MouseMove(TShiftState Shift,int X, int Y) if (DragStart) Rotation.x+=(float)(X-Start.x)/2.0*M_PI/180.0; // ๊ฒฝ๋๋ณํ๋ Rotation.y+=(float)(Y-Start.y)/2.0*M_PI/180.0; // ์๋๋ณํ๋ CalculateViewport(); // ์์ ์ฌ๊ณ์ฐ Start.Set(X,Y); // ๋ง์ฐ์ค์์์ ์ฌ์ค์ return true; return false; void ::MouseUp(TMouseButton Button,TShiftState Shift, int X, int Y) if (DragStart) DragStart=false; 31 ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ํ์ ์์ ์ฌ๊ณ์ฐ void ::CalculateViewport() TPoint3D O,YAxis,Normal; O.Set(0,0,0); YAxis.Set(0,1,0); // ๊ฒฝ๋๋ฐฉํฅํ์ EyePoint=O_EyePoint.RotatedAbout(O_SceneCenter,YAxis,Rotation.x); UpVector=O_UpVector.RotatedAbout(O,YAxis,Rotation.x); // ์๋๋ฐฉํฅํ์ Normal=O_SceneCenter.CrossProduct(EyePoint,O_SceneCenter+YAxis); Normal.Normalize(); EyePoint=EyePoint.RotatedAbout(O_SceneCenter,Normal,Rotation.y); UpVector=UpVector.RotatedAbout(O,Normal,Rotation.y); 32
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ์ด๋ ์์ ์ด๋์ํ์ํ๋ณ์์ถ๊ฐ class... bool DragStart,Rotating; float Distance; TPoint3D O_SceneCenter,O_EyePoint,O_UpVector; TPoint2D Rotation,Start;... ::()... Distance=100; CalculateViewport(); 33 ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ์ด๋ ์์ ์ด๋์ํ์ํ์ฝ๋์ถ๊ฐ void ::MouseDown(TMouseButton Button,TShiftState Shift, int X, int Y) if (!DragStart) DragStart=true; Start.Set(X,Y); Rotating=(Button==mbLeft); 34
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ์ด๋ ์์ ์ด๋์ํ์ํ์ฝ๋์ถ๊ฐ bool ::MouseMove(TShiftState Shift,int X, int Y) if (DragStart) if (Rotating) Rotation.x+=(float)(X-Start.x)/2.0*M_PI/180.0; Rotation.y+=(float)(Y-Start.y)/2.0*M_PI/180.0; else float dy=y-start.y; if (dy>0) Distance*=1.02f; else Distance*=0.98f; CalculateViewport(); Start.Set(X,Y); return true; return false; 35 ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ์ด๋ ์์ ์ด๋์ํ์ํ์ฝ๋์ถ๊ฐ void ::CalculateViewport() TPoint3D O,YAxis,Normal; O.Set(0,0,0); YAxis.Set(0,1,0); O_EyePoint.Set(0,0,Distance); EyePoint=O_EyePoint.RotatedAbout(O_SceneCenter,YAxis,Rotation.x); UpVector=O_UpVector.RotatedAbout(O,YAxis,Rotation.x); Normal=O_SceneCenter.CrossProduct(EyePoint,O_SceneCenter+YAxis); Normal.Normalize(); EyePoint=EyePoint.RotatedAbout(O_SceneCenter,Normal,Rotation.y); UpVector=UpVector.RotatedAbout(O,Normal,Rotation.y); ์์ ์์ํ์ข์ฐ๋ก์ด๋ํ๋ ค๋ฉด์ด๋ป๊ฒํด์ผํ ๊น? (Homework) 36
ํ ์คํธํ๋ก๊ทธ๋จ๊ฐ๋ฐ ์์ ์ด๊ธฐํ ๋ฉ๋ด๋ฅผ์ถ๊ฐ void fastcall TMainForm::InitializeViewport1Click(TObject *Sender) if (GL) GL->InitViewport(100); FormPaint(this); void ::InitViewport(float dist) Distance=dist; O_SceneCenter.Set(0,0,0); O_UpVector.Set(0,1,0); Rotation.Set(0,0); CalculateViewport(); ::(HDC DC,int l,int b,int r,int t)... InitViewport(100); DragStart=false; 37