Digital 3D Anthropometry 6. Body Data Class Sungmin Kim SEOUL NATIONAL UNIVERSITY Body Data Class 의설계 Body Model 의관리 인체데이터입출력 데이터불러오기 인체모델그리기 TOpenGL의확장 프로젝트관리 프로젝트저장 / 불러오기 추가기능구현 좌표축정렬 Face, Wireframe, Translucent 보기 GUI 이슈 화면일부에 TOpenGL 구현 Introduction 2
Class 의설계 생성자와파괴자 class public: (); ~(); ; TModel3D void *Model; LoadModel(AnsiString); ::() Model=0; ::~() if (Model) delete Model; Model=0; 3 Class 의설계 인체모델불러오기 void ::LoadModel(AnsiString N) if (Model) delete Model; Model=new TModel3D; AnsiString E=ExtractFileExt(N).UpperCase(); if (E==".PLY") Model->LoadFromASCIIPLY(N); if (E==".STL") Model->LoadFromBinarySTL(N); 4
인체데이터의표시 테스트프로그램제작 기본 SDI 프로그램제작 BodyAnalyzer.bpr 로저장 메뉴와 TOpenDialog 를추가 Filter 를설정 DefaultExt=ply Name=LOADBODY InitialDir=. Options 중 ofoverwriteprompt, ofhidereadonly, ofextensiondifferent, ofpathmustexist, offilemustexist, ofcreateprompt, ofshareaware = true 5 인체데이터의표시 테스트프로그램제작 TMainForm.h #include ".h" class TMainForm : public TForm TOpenGL *GL; *Body; ; TMainForm.cpp fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) GL=0; Body=0; void fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) if (GL) delete GL; GL=0; if (Body) delete Body; Body=0; Action=caFree; 6
인체데이터의표시 테스트프로그램의제작 Begin New Project Handler 작성 void fastcall TMainForm::BeginNewProject1Click(TObject *Sender) LOADBODY->FileName=""; if (LOADBODY->Execute()) if (Body) delete Body; Body=new ; Body->LoadModel(LOADBODY->FileName); FormPaint(this); 7 인체데이터의표시 테스트프로그램의제작 FormPaint 에서인체데이터를그리기 void fastcall TMainForm::FormPaint(TObject *Sender) if (GL) GL->BeginDraw(Canvas->Handle); if (Body) Body->Draw(GL); GL->EndDraw(Canvas->Handle);.h #include "TOpenGL.h" class public: void Draw(TOpenGL*); ;.cpp void ::Draw(TOpenGL *GL) if (Model) GL->Draw(Model); 8
인체데이터의표시 TOpenGL 클래스에 TModel3D 를그리는함수를추가 TOpenGL.h #include "TModel3D.h" // TPoint3D.h 대신 class TOpenGL Draw(TModel3D*); ; TOpenGL.cpp void TOpenGL::Draw(TModel3D *M) int i,j; glbegin(gl_triangles); for(i=0;i<m->elemnum;i++) for(j=0;j<3;j++) int e=m->elem[i*3+j]; glnormal3f(m->normal[e].x,m->normal[e].y,m->normal[e].z); glcolor3f(m->color[e].x,m->color[e].y,m->color[e].z); glvertex3f(m->node[e].x,m->node[e].y,m->node[e].z); glend(); 9 인체데이터의표시 인체데이터불러오기 ASCII Ply 기본시점을 100 에서 2000 으로변경 Binary STL 10
프로젝트관리 프로젝트저장 / 불러오기함수구성 메뉴및다이얼로그박스구성 표준적인파일저장하기 / 불러오기용으로설정 파일확장자는 prj 정도로 11 프로젝트관리 메뉴핸들러작성 void fastcall TMainForm::LoadProject1Click(TObject *Sender) LOADPROJECT->FileName=""; if (LOADPROJECT->Execute()) if (Body) delete Body; Body=new ; Body->LoadFromFile(LOADPROJECT->FileName); FormPaint(this); void fastcall TMainForm::SaveProject1Click(TObject *Sender) if (Body) SAVEPROJECT->FileName=""; if (SAVEPROJECT->Execute()) Body->SaveToFile(SAVEPROJECT->FileName); 12
프로젝트관리 프로젝트저장 / 불러오기함수작성 void ::SaveToFile(AnsiString N) TNewFileStream *F=new TNewFileStream(N,fmCreate); F->WInt(1); // yyyy-mm-dd (date) Model->SaveToFileStream(F); delete F; void ::LoadFromFile(AnsiString N) TNewFileStream *F=new TNewFileStream(N,fmOpenRead); int Version; F->RInt(&Version); Model=new TModel3D; Model->LoadFromFileStream(F); delete F; 13 추가기능구현 좌표축정렬 모델을 X, Y, Z 축으로회전시키는기능이필요함 일단좌표축을그려야함 void TOpenGL::DrawAxis(float l) gldisable(gl_lighting); glbegin(gl_lines); glcolor3f(1,0,0); glvertex3f(0,0,0); glvertex3f(l,0,0); glcolor3f(0,1,0); glvertex3f(0,0,0); glvertex3f(0,l,0); glcolor3f(0,0,1); glvertex3f(0,0,0); glvertex3f(0,0,l); glend(); glenable(gl_lighting); void fastcall TMainForm::FormPaint(TObject *Sender) if (GL) GL->BeginDraw(Canvas->Handle); GL->DrawAxis(1000); if (Body) Body->Draw(GL); GL->EndDraw(Canvas->Handle); 14
추가기능구현 좌표축정렬 다이얼로그박스만들기 void fastcall TRotateModelDialog::Button1Click(TObject *Sender) Result=1; Close(); void fastcall TRotateModelDialog::Button2Click(TObject *Sender) Result=0; Close(); 15 추가기능구현 좌표축정렬 메뉴추가및핸들러작성 void fastcall TMainForm::RotateModel1Click(TObject *Sender) if (Body) RotateModelDialog->ShowModal(); if (RotateModelDialog->Result) int axis; if (RotateModelDialog->X->Checked) axis=0; if (RotateModelDialog->Y->Checked) axis=1; if (RotateModelDialog->Z->Checked) axis=2; Body->RotateModel(axis,RotateModelDialog->ANGLE->Text.ToDouble()); FormPaint(this); 16
추가기능구현 좌표축정렬 모델을회전하는함수작성 void ::RotateModel(int axis,float angle) angle=angle*m_pi/180.0f; TPoint3D O; O.Set(0,0,0); if (axis==0) Model->Rotate(O,angle,0,0); if (axis==1) Model->Rotate(O,0,angle,0); if (axis==2) Model->Rotate(O,0,0,angle); 17 추가기능구현 Face, Wireframe, Translucent 보기 메뉴추가 void fastcall TMainForm::FaceWireframe1Click(TObject *Sender) if (Body) Body->ViewFace=1-Body->ViewFace; FormPaint(this); void fastcall TMainForm::OpaqueTranslucent1Click(TObject *Sender) if (Body) Body->Opaque=1-Body->Opaque; FormPaint(this); 18
추가기능구현 Face, Wireframe, Translucent 보기.h 와 TModel3D.h 에 ViewFace,Opaque 변수를추가 ::() Model=0; ViewFace=1; Opaque=1; void ::Draw(TOpenGL *GL) if (Model) Model->ViewFace=ViewFace; Model->Opaque=Opaque; GL->Draw(Model); TModel3D::TModel3D() NodeNum=0; Node=Color=Normal=0; ElemNum=0; Elem=0; ViewFace=1; Opaque=1; 19 추가기능구현 Face, Wireframe, Translucent 보기 TOpenGL 의 Draw 함수를수정 void TOpenGL::Draw(TModel3D *M) int i,j,e; float o; TPoint3D *N,*C,*P; N=M->Normal; C=M->Color; P=M->Node; if (M->ViewFace) glbegin(gl_triangles); if (M->Opaque) o=1.0f; else o=0.5f; for(i=0;i<m->elemnum;i++) for(j=0;j<3;j++) e=m->elem[i*3+j]; glnormal3f(n[e].x,n[e].y,n[e].z); glcolor4f(c[e].x,c[e].y,c[e].z,o); glvertex3f(p[e].x,p[e].y,p[e].z); glend(); else for(i=0;i<m->elemnum;i++) glbegin(gl_line_loop); for(j=0;j<3;j++) e=m->elem[i*3+j]; glnormal3f(n[e].x,n[e].y,n[e].z); glcolor3f(c[e].x,c[e].y,c[e].z); glvertex3f(p[e].x,p[e].y,p[e].z); glend(); 20
추가기능구현 Face, Wireframe, Translucent 보기 Translucent 표현을위해 BeginDraw 를수정 void TOpenGL::BeginDraw(HDC DC) glenable(gl_color_material); glenable( GL_BLEND); glblendfunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 21 GUI 이슈 화면일부에 TOpenGL 구현 화면일부에 TOpenGL을구현하고나머지에 UI 를구성하려면? 여러개의 TOpenGL 을하나의창에구현하려면? PFD_DRAW_TO_BITMAP? 의외로잘작동하지않음 Panel과 Timer를써서해결가능 22
GUI 이슈 화면일부에 TOpenGL 구현 LEFT RIGHT 23 GUI 이슈 화면일부에 TOpenGL 구현 void fastcall TMainForm::FormCreate(TObject *Sender) GL=new TOpenGL(GetDC(RIGHT->Handle),0,0,RIGHT->Width,RIGHT->Height); void fastcall TMainForm::FormResize(TObject *Sender) if (GL) delete GL; GL=new TOpenGL(GetDC(RIGHT->Handle),0,0,RIGHT->Width,RIGHT->Height); Redraw(); FormPaint 를 Redraw 로교체 모든 FormPaint(this) 를 Redraw() 로교체 void fastcall TMainForm::Redraw() if (GL) GL->BeginDraw(GetDC(RIGHT->Handle)); GL->DrawAxis(1000); if (Body) Body->Draw(GL); GL->EndDraw(GetDC(RIGHT->Handle)); 24
GUI 이슈 화면일부에 TOpenGL 구현 Timer event 에서 Redraw 를호출해서화면을강제갱신 void fastcall TMainForm::Timer1Timer(TObject *Sender) Redraw(); Form 의 mouse event handler 를 RIGHT 의 mouse event handler 로교체 void fastcall TMainForm::RIGHTMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) if (GL) GL->MouseDown(Button,Shift,X,Y); void fastcall TMainForm::RIGHTMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) if (GL) if (GL->MouseMove(Shift,X,Y)) Redraw(); void fastcall TMainForm::RIGHTMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) if (GL) GL->MouseUp(Button,Shift,X,Y); 25 GUI 이슈 화면일부에 TOpenGL 구현 26
GUI 이슈 화면일부에 TOpenGL 구현 UI 구성 메뉴와직접관련된버튼들은 OnClick 이벤트에메뉴의이벤트핸들러를연결 27 GUI 이슈 화면일부에 TOpenGL 구현 Rotate 버튼의 handler 구현 void fastcall TMainForm::Button4Click(TObject *Sender) if (Body) Body->RotateModel(AXIS->ItemIndex,ANGLE->Text.ToDouble()); Redraw(); 부분 OpenGL 렌더링을써서 Dialog box 보다더간단한 UI 구성이가능 28