Digital 3D Anthropometryfashiontech.snu.ac.kr/note/BodyMeasurement/06-Body Data... ·...
Transcript of Digital 3D Anthropometryfashiontech.snu.ac.kr/note/BodyMeasurement/06-Body Data... ·...
Sungmin Kim
SEOUL NATIONAL UNIVERSITY
Digital 3D Anthropometry
6. Body Data Class
Introduction Body Data Class 의 설계 Body Model 의 관리
인체 데이터 입출력
– 데이터 불러오기
인체 모델 그리기
– TOpenGL의 확장
프로젝트 관리
– 프로젝트 저장/불러오기
추가 기능 구현
– 좌표축 정렬
– Face, Wireframe, Translucent 보기
GUI 이슈
– 화면 일부에 TOpenGL 구현
2
TBodyData TBodyData Class의 설계 생성자와 파괴자
3
class TBodyData{public:
TBodyData();~TBodyData();
TModel3D *Model;
void LoadModel(AnsiString);};
TBodyData::TBodyData(){Model=0;}
TBodyData::~TBodyData(){if (Model) delete Model;Model=0;}
TBodyData TBodyData Class의 설계 인체 모델 불러오기
4
void TBodyData::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);}
TBodyData 인체 데이터의 표시 테스트 프로그램 제작
기본 SDI 프로그램 제작
– BodyAnalyzer.bpr 로 저장– 메뉴와 TOpenDialog 를 추가
5
Filter 를 설정
DefaultExt=plyName=LOADBODYInitialDir=.Options 중
ofOverwritePrompt, ofHideReadOnly, ofExtensionDifferent, ofPathMustExist, ofFileMustExist,ofCreatePrompt, ofShareAware = true
TBodyData 인체 데이터의 표시 테스트 프로그램 제작
6
...#include "TBodyData.h"...class TMainForm : public TForm{...
TOpenGL *GL;TBodyData *Body;
};
__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;}
TMainForm.h
TMainForm.cpp
TBodyData 인체 데이터의 표시 테스트 프로그램의 제작
Begin New Project Handler 작성
7
void __fastcall TMainForm::BeginNewProject1Click(TObject *Sender){LOADBODY->FileName="";if (LOADBODY->Execute()){
if (Body) delete Body;Body=new TBodyData;Body->LoadModel(LOADBODY->FileName);FormPaint(this);}
}
TBodyData 인체 데이터의 표시 테스트 프로그램의 제작
FormPaint 에서 인체 데이터를 그리기
8
void __fastcall TMainForm::FormPaint(TObject *Sender){if (GL){
GL->BeginDraw(Canvas->Handle);if (Body){
Body->Draw(GL);}
GL->EndDraw(Canvas->Handle);}
}
...#include "TOpenGL.h"...class TBodyData{public:...
void Draw(TOpenGL*);};
TBodyData.h
void TBodyData::Draw(TOpenGL *GL){if (Model) GL->Draw(Model);}
TBodyData.cpp
TBodyData 인체 데이터의 표시 TOpenGL 클래스에 TModel3D를 그리는 함수를 추가
9
...#include "TModel3D.h" // TPoint3D.h 대신...
class TOpenGL{...
Draw(TModel3D*);};
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();}
TOpenGL.h
TOpenGL.cpp
TBodyData 인체 데이터의 표시 인체데이터 불러오기
10
ASCIIPly
BinarySTL
기본 시점을100 에서
2000으로 변경
TBodyData 프로젝트 관리 프로젝트 저장/불러오기 함수 구성
메뉴 및 다이얼로그박스 구성
– 표준적인 파일 저장하기/불러오기용으로 설정– 파일 확장자는 prj 정도로
11
TBodyData 프로젝트 관리 메뉴 핸들러 작성
12
void __fastcall TMainForm::LoadProject1Click(TObject *Sender){LOADPROJECT->FileName="";if (LOADPROJECT->Execute()){
if (Body) delete Body;Body=new TBodyData;Body->LoadFromFile(LOADPROJECT->FileName);FormPaint(this);}
}
void __fastcall TMainForm::SaveProject1Click(TObject *Sender){if (Body){
SAVEPROJECT->FileName="";if (SAVEPROJECT->Execute()){
Body->SaveToFile(SAVEPROJECT->FileName);}
}}
TBodyData 프로젝트 관리 프로젝트 저장/불러오기 함수 작성
13
void TBodyData::SaveToFile(AnsiString N){TNewFileStream *F=new TNewFileStream(N,fmCreate);F->WInt(1); // yyyy-mm-dd (date)Model->SaveToFileStream(F);delete F;}
void TBodyData::LoadFromFile(AnsiString N){TNewFileStream *F=new TNewFileStream(N,fmOpenRead);int Version;F->RInt(&Version);Model=new TModel3D;Model->LoadFromFileStream(F);delete F;}
TBodyData 추가 기능 구현 좌표축 정렬
모델을 X, Y, Z 축으로 회전시키는 기능이 필요함
일단 좌표축을 그려야 함
14
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);}
}
TBodyData 추가 기능 구현 좌표축 정렬
다이얼로그 박스 만들기
15
void __fastcall TRotateModelDialog::Button1Click(TObject *Sender){Result=1;Close(); }
void __fastcall TRotateModelDialog::Button2Click(TObject *Sender){Result=0;Close(); }
TBodyData 추가 기능 구현 좌표축 정렬
메뉴 추가 및 핸들러 작성
16
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);}
}}
TBodyData 추가 기능 구현 좌표축 정렬
모델을 회전하는 함수 작성
17
void TBodyData::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);}
TBodyData 추가 기능 구현 Face, Wireframe, Translucent 보기
메뉴 추가
18
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);}
}
TBodyData 추가 기능 구현 Face, Wireframe, Translucent 보기
TBodyData.h 와 TModel3D.h 에 ViewFace,Opaque 변수를 추가
19
TBodyData::TBodyData(){Model=0;ViewFace=1;Opaque=1;}
void TBodyData::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;}
TBodyData 추가 기능 구현 Face, Wireframe, Translucent 보기
TOpenGL 의 Draw 함수를 수정
20
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();}
}}
TBodyData 추가 기능 구현 Face, Wireframe, Translucent 보기
Translucent 표현을 위해 BeginDraw 를 수정
21
void TOpenGL::BeginDraw(HDC DC){...glEnable(GL_COLOR_MATERIAL);glEnable( GL_BLEND);glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);...}
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
화면 일부에 TOpenGL을 구현하고 나머지에 UI 를 구성하려면 ?
여러 개의 TOpenGL 을 하나의 창에 구현하려면 ?
PFD_DRAW_TO_BITMAP ?
– 의외로 잘 작동하지 않음
Panel과 Timer를 써서 해결 가능
22
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
23
LEFT RIGHT
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
FormPaint 를 Redraw로 교체
– 모든 FormPaint(this) 를 Redraw()로 교체
24
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();}
void __fastcall TMainForm::Redraw(){if (GL){
GL->BeginDraw(GetDC(RIGHT->Handle));GL->DrawAxis(1000);if (Body){
Body->Draw(GL);}
GL->EndDraw(GetDC(RIGHT->Handle));}
}
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
Timer event 에서 Redraw를 호출해서 화면을 강제 갱신
Form 의 mouse event handler 를 RIGHT 의 mouse event handler 로 교체
25
void __fastcall TMainForm::Timer1Timer(TObject *Sender){Redraw();}
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);}
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
26
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
UI 구성
27
메뉴와 직접 관련된 버튼들은 OnClick 이벤트에메뉴의 이벤트 핸들러를 연결
TBodyData GUI 이슈 화면 일부에 TOpenGL 구현
Rotate버튼의 handler 구현
부분 OpenGL 렌더링을 써서 Dialog box 보다 더 간단한 UI 구성이 가능
28
void __fastcall TMainForm::Button4Click(TObject *Sender){if (Body){
Body->RotateModel(AXIS->ItemIndex,ANGLE->Text.ToDouble());Redraw();}
}