[MFC :: OpenGL] DXF :: Part 4 (옮김)

심플디 2014.04.25 12:55 조회 수 : 1490



DXF_03.zip

Test_Vertex 2.dxf

Test_Vertex.dxf






Part 3를 통해 실전 가능한 DXF 클래스를 만들어 보았다.


그럼 내친김에 Nurbs curve까지 한큐에 가보자.













아마 여태껏 독자들은.

ProjectOpenGL 프로젝트를 벗어난 DXF 프로젝트에서 "이 새끼가 드디어 글 쓰기 귀찮아서 싸지르고 보는구나." 란 생각을 했을 것이다.

하지만, 이는 필자의 표현력이 부족해서 그런것이니 많은 양해를 구한다.

필자는 한번 글을 쓰고는 정말 많이 소리내며 읽어본다.

말이 어색하지는 않은지, 이해가 쉽게 되는지, 오해를 살 여지가 있는지.

필자의 글은, 첫 운을 띄울때 거의 감정적으로 기록되고, 여러번 읽고 수정되며 객관적인 글이 된다.


그러니 혹시 이해가 잘 안가더라도 꾹 참고 읽어주기를 바란다.

왜냐하면 아직 프로젝트가 진행중이며, 문법을 수정할 정도로 시간이 여유롭지 않기 때문이다.


그리고 이 게시물을 기점으로 다시 ProjectOpenGL 프로젝트가 진행된다.

물론 DXF 프로젝트에서 쓴 클래스를 옮겨와서 사용 할 것이다.


혹시 DXF 프로젝트가 다 개소리로 들렸다고 해도, 개의치 않는다.

첨부파일을 올려놓았으니 ( DXF_03.zip ) 이해하기 싫다면 옮겨 쓰기만 하면 된다.


<그림 1 :: 프로젝트 ProjectOpenGL의 변화>


<그림 1>은 프로젝트 ProjectOpenGL의 선언부(.h)에 cl~ 시리즈들을 추가시킨 모습을 보여주고 있다.

물론 구현부(.cpp)에도 관련 cpp 파일을 추가시켜주어야 한다.

관련 파일은 전부 첨부파일 ( DXF_03.zip )에 들어있으니 갖다 쓰기 바란다.



<그림 2 :: 전역 선언>


<그림 3 :: Doc 클래스 선언부에 clPoint2 변수 선언>


옮겨다 쓰는 만큼, DXF 프로젝트의 형식을 그대로 따른다.

<그림 2>는 clPoint2와 clSFunction.h 클래스를 전역 선언하는 코드를 보여주고 있다.

또한 <그림 3>과 같이 ProjectOpenGL 프로젝트의 문서클래스인 Doc 클래스 선언부(.h)에 clPoint2 변수 vlPoint2를 선언하였다.


<그림 4 :: Doc 클래스 구현부에 clInputManager 클래스 선언>


<그림 5 :: Doc 클래스 Serialize 메서드의 수정>



<그림 4>와 <그림 5>는 DXF프로젝트에서 했던 방식을 그대로 따라하고 있다.


 

 

<그림 6 :: 눫스 커브 그리기 메서드 수정>


<그림 6>은 Doc의 변수를 끌어오는 메커니즘을 소개하고 있다.

Doc 변수를 View에서 가져오는것은 이처럼 쉽지만, View 변수를 Doc에서 가져오는것은 그리 간단하지 않다.

그것은 나중에 기회가 되면 소개하도록 하겠다.


 

 <그림 7 :: 눫스 커브 제어점 그리기 메서드 수정>



<그림 8 :: 돼지저금통>


 

<그림 9 :: Perspective 돼지저금통>

 

<그림 10 :: AutoCAD 로 볼 수 있는 돼지저금통>



<그림 8>과 <그림 9>는 OpenGL로 본 돼지저금통의 모습을 보여주고 있다.

<그림 10>은 AutoCAD 2010으로 본 돼지저금통의 모습이다.

이로서, 점 Data를 가져오는 일에는 성공했다.


하지만 아직 버그가 있는데, 바로 '면 생성'이 되지 않았다는 점이다. (회전해서 보기 불편한 점은 일단 제외하자)

왜 이럴까...?


 <그림 11 :: 점 데이타>


  

 <그림 12 :: Test_Vertex.dxf >


<그림 13 :: 불러오기 결과>


이를 위해 DXF 포맷을 가장한 점 데이타를 <그림 12>와 같이 설정 파일로 만들어보았다.

하지만 결과는 '면' 이 아니였다.


<그림 14 :: 넓스 커브의 제어점을 그리는 코드>


(속 상해서 한숨 자고 맥주 한 피트 따고 오징어 좀 씹고 옴) (왜 이렇게 한큐에 해결되는게 없지?)

<그림 14>는 제어점만 그리는 코드를 보여주고 있다. 이것저것 고치다 발견한 것인데, 이것은 현재 좌표 배열이 동적할당 방식이라서 생긴 문제 같다.

실행시 디버그를 해보았는데, Heap memory 의 손실(?)에 의해 에러가 났다고 알려주었다.

점(Point) 출력은 백날 잘 되는데... 왜 면(Surface) 출력에서만 에러가 나나...


혹시 몰라서 float 형을 GLfloat 형으로 모두 바꾸고, 동적 할당 데이터 타입도 float 형에서 GLfloat 형으로 교체해보았다.

그래도 안 되었다.

동적 할당 방식을 스위스 은행 뺨칠 정도로 안전하게 바꾸고, 모든 코드를 요목조목 다 살펴보았다.

그래도 안 되었다.

혹시 View클래스와 Doc 클래스간의 교류가 원활하지 않아서 Heap오류가 난 듯한 느낌이 났었다.

그래서 View 클래스에서 GLfloat형 변수를 동적 할당 하고, Doc의 vlPoint2변수에서 좌표 변수를 전달받기도 해보았다.

그래도 안 되었다.

혹시 파일 포맷이 거지같아서 에러가 나는것인가 해서, 파일포맷도 처음부터 꼼꼼하게 바꿔보았다.

U 및 V의 출력이 순차적으로 정상상태로 이루어지는가 검사해가며 파일을 다시 만들어 보았다.

그래도 안 되었다.


하지만 딱, 한 가지.

이미 정적 상태로 배열된 변수에 동적 배열 변수의 값을 초기화 시키고,

Nurbs 함수에 정적함수를 대입하면 

잘 실행이 되었다.



이제 필자가 생각해 낼 만한 방법은 하나밖에 없다. '정적배열'의 사용이다.

메모리의 손실을 막고자 동적할당을 선택했지만, double 형도 아니고 고작 float형인데, 

고작 수 천개에 대한 손실을 막으려고 몇날 몇일을 밤새는 작업을 한다는 것은 너무 말이 되지 않는다.

사실 고작 6면체 돌리는 함수를 직접 만들고 그림자 생성시킨 것 까지만 해본 나에게 이 정도 진도를 온것도 엄청난 일이다.

누가 옆에서 조언해주는것도 아니고, 학기도 끝나가는데 이렇게 뭐 하나 할때마다 2~3일씩 시간을 소비하는 짓은 이제 도저히 못 해먹겠다.

(필자가 보통 [MFC :: OpenGL]의 게시물을 하나 쓰기까지 평균 2.5일이 걸린다는 것을 아시는가?)

그리고 사실 말이 좋아 "동적할당의 장점"이 메모리의 손실을 막는거지만,

동적할당 후, 해제한다고 해서 메모리를 차지했던 공간까지 해제되는 것은 아니다.

동적 해제 후, 같은 값으로 또 다시 동적 할당을 하면, 해당 exe 프로그램이 메모리를 차지하는 양은 그대로 누적된다.

무슨 말을 하는거냐면, 

만약 500개의 좌표를 저장하는 배열을 동적할당했는데, 1000개의 좌표가 들어있는 파일로 교체한다면

exe 파일은 500 -500 +1000 = 1000 의 메모리를 차지하는 것이 아니라, 500 + 1000 = 1500 의 메모리를 차지하게 되는 것이다.

또한 실제로 이것은 점의 개수만큼 배열을 할당하지 않고, u 및 v의 크기만큼 배열을 할당하므로 그 손실은 엄청나다.

따라서 아예 정적배열을 크게 선언하는 것도 나쁘게 볼일이 아니다.


<그림 15 :: Array>


<그림 16 :: Array 변경>


 

<그림 17 :: <그림 16>의 결과>

 

<그림 18 :: 확장된 Array 크기에 대한 결과값>

 

 

그러나, <그림 15>와 같이 배열을 선언해주어야만 한다.

Knots 와 온갖 변수들을 전부 세팅해도 <그림 16>과 같이 배열크기가 달라지면 <그림 17>과 같이 형상이 비틀리게 된다....

또한 NurbsPoint2[5000][5000][3]으로 설정하게 되면 <그림 18>과 같이 거의 평면수준의 '면'을 하나 얻을 수 있다.

(여기서 잠깐. NurbsPoint2[5000][4][3]으로 선언하면 아무런 문제가 발생하지 않는다.)


<그림 19 :: 간격 조정> 


<그림 19>는 NurbsPoint2의 v차수 변경 (NurbsPoint2[5000][5000][3])에 대응하는 수정사항을 보여주고 있다.

이와 같이 수정을 하면 U 및 V 배열 내의 좌표만 인식하는 Nurbs curve가 완성된다.


<그림 20 :: 결과>


<그림 20>을 통해 Nurbscurve가 정상적으로 출력된 모습을 볼 수 있다.

5000 x 5000의 배열 중, 6 x 4를 제외하면 전부 (0, 0, 0)의 좌표가 초기화 되어 있을텐데, OpenGL의 화면상 0,0,0 위치에는 그 어떤 점도 찍혀있지 않음을 볼 수 있다.


이것은 <그림 19>와 같은 수정을 통해 배열의 범위를 확실하게 정의하고,

iu 및 iv와 같이 배열의 유효 길이를 적절하게 선언하고, fknots_u 및 fknots_v와 같이 영향력 변수도 적절하게 초기화 시켜주면,

NurbsCurve를 표현하기에 무리가 없다는 것을 의미한다.

(2011.11.04)



무효범위의 값을 쳐 내는 일은 했지만, 아직 할일이 더 남았다.

바로 Sorting 작업이다.


 <그림 21 :: Test 모드의 좌표 상태>

 

<그림 22 :: Scanning 모드의 좌표 상태>

 

우리는 여지껏 <그림 21>처럼 좌표를 배열하여 Nurbs를 그려왔다. 하지만 실제로 3D Scanning은 좌표값을 <그림 22>처럼 듬성듬성 기록한다.

이전에 첨부했던 돼지저금통의 스캐닝 data를 텍스트 파일로 열어보면 그 사실을 알 수 있다.

이것은 스캐닝 프로그램이 변화가 없는 스캔 부위를 기록하지 않는 탓이다. (레알 평면 상태라면 아무리 긴 스캔라인이라도 점이 2개 찍힐 수가 있다.)


골치아픈 문제이지만 어짜피 '편집'을 하려면 이정도는 감수해야 한다.

이것은 편집의 문제이기도 하다. (진도가 '편집'의 '삭제'까지 갈지는 미지수...)


<그림 23 :: 결과>

 <그림 24 :: 좌표 값>


<그림 23>의 '점'들을 통해 <그림 22>의 결과가 정상임을 알 수 있다.

단 하나 문제가 있다면 Curve가 꼬여 있다는 것이다...


분명 '점'의 위치는 <그림 24>와 같겠지만, 배열상의 '점'의 위치는 <그림 22>와 같기 때문에, 

v=3 라인을 제외한 모든 v라인은 최종적으로 0,0,0을 향해 꼬구라 지는 형태를 띈다.

이를 통해 정상 배열인 v(3)라인도 영향을 받아 최종적으로 0,0,0의 마성에 넘어간 것이다.


<그림 25 :: 대안 1>


<그림 26 :: 결과>

 

<그림 25>는 대안책을 제시하고 있다.

sorting의 개념과는 무색하지만, 일단 이런 식으로라도  잉여좌표(0, 0, 0)의 영향으로 인한 곡면의 왜곡을 막아야 했다.

결과는 대략 성공적이지만 만족할만한 수준은 아니다.

잉여점들이 전부 우측으로 쏠렸기 때문에, Nurbscurve가 우측쪽으로만 촘촘한 것을 볼 수 있다.

엄연히 말하자면 '불량품'이다. 하지만 땜빵질을 하기에는 더 없이 괜춘한 아이디어다. ('괜춘한' 오타 아님ㅋ)


 <그림 27 :: 돼지저금통>



<그림 27>은 Sorting 을 하지 않은 돼지저금통의 모습이다. (역시 면은 보이지 않고, 점들만 보인다.)

원인은 알 수 없는데, Scanning data의 Sorting 과정에서 프로그램이 멈추고 종료되는 버그를 발견했다.

소수의 점은 버그 없이 잘만 돌아가더니, 왜 또 이 지랄일까...





각종 오류로 심신이 피로하여 게시물을 일단 여기서 끊어야 되겠다.

게시물이 길면, 편집하는 사람도 피곤하고 보는 사람도 피곤하다.


그리고 첨부파일에 있는것은 '참고'로 보는 것이지 '전체'를 보는 것이 아니다.

첨부파일은 File I/O의 틀이 완성되는 대로 다시 올릴 것이다.

Sorting에 관련되어 수정되는 부분이 현재도 아주 많다.

거듭 말하지만 '참고'용으로만 봐주기를 부탁한다.













 <그림 28 :: 돼지저금통 >


 <그림 29 :: 접촉식 3D scanning>


삼천포로 빠져보자. 

스캐닝 데이터의 편집의 필요성을 설명하려 한다. 


<그림 28>은 실제 스캐닝한 대상이다. 

<그림 27>을 보면 알겠지만, z축 기준으로 거의 절반밖에 스캐닝 되지 않았다. 이것은 <그림 29>와 같은 접촉식 스캐너의 한계다.

굴곡을 저장하는데 있어서 아래에 있는 것 까지 상세하게 저장하는것은 할 수 없다.

영상 스캐닝처럼 물체를 회전시키며 스캐닝을 하는 방법도 있지만, 접촉식보다 정밀함을 기대하기는 힘들다.

(물론 영상 스캐닝도, 기술이 좋아져서 정밀함이 많이 나아졌다.)


아무튼 모든 면을 한번에 Scanning 하는것은 불가능 하다. 

물체의 대상에 따라서 가능할 수도 있지만, 그런 Object는 흔하지 않다.


특히 <그림 29>와 같은 접촉식에 있어서, Object를 완벽히 표현하려면 윗면을 스캔하고, 뒤집어서 아랫면을 스캔하고, 붙여야 한다.

그리고 윗면을 스캔한 스캐닝 데이터의 일정 부분을 날려야 하고, 아랫면을 스캔한 스캐닝 데이터의 일정 부분을 날려야 한다.

그 다음, 그 두개의 스캐닝 데이터를 합치면 된다.


또한 때때로 박판 성형 제품을 스캐닝 한다면, 윗면 데이터와, 아랫면 데이터의 비교를 통한 잘라내기가 있어야 한다.

(알고리즘이 복잡할 것 같다.)


가장 중요한 것은, 설계 파일과, 스캐닝 파일과의 치수 오차를 분석하는 것이다.

(알고리즘이 짜증날 것 같다.)

번호 제목 글쓴이 날짜 조회 수
공지 본 게시글의 첨부파일 권한 심플디 2014.08.22 2401
47 [MFC :: OpenGL] 컴공 수업 발표 자료 (옮김) [2] 심플디 2014.04.25 2899
46 [MFC :: OpenGL] Project 시즌 2 후기 (옮김) 심플디 2014.04.25 1585
45 [MFC :: OpenGL] File output (옮김) 심플디 2014.04.25 1519
44 [MFC :: OpenGL] Tool bar(툴바) 편집방법 (옮김) 심플디 2014.04.25 1840
43 [MFC :: OpenGL] IntroPage (옮김) file 심플디 2014.04.25 1518
42 [MFC :: OpenGL] IPC 적용 (옮김) file 심플디 2014.04.25 1574
41 MFC :: OpenGL] ProjectMFCReport 와꾸짜기 (옮김) 심플디 2014.04.25 1734
40 [MFC :: OpenGL] Data Dialog 와꾸짜기 (옮김) 심플디 2014.04.25 1728
39 [MFC :: OpenGL] 시즌 2 개요 (옮김) file 심플디 2014.04.25 1515
38 [MFC :: OpenGL] Project 시즌 2 시작 (옮김) [1] 심플디 2014.04.25 1522
37 [MFC :: OpenGL] Project 시즌 1 후기 (옮김) file 심플디 2014.04.25 1584
36 [MFC :: OpenGL] Mesh :: Part 2 (옮김) [1] file 심플디 2014.04.25 1551
35 [MFC :: OpenGL] Mesh :: Part 1 (옮김) file 심플디 2014.04.25 1600
34 [MFC :: OpenGL] DXF :: Part 5 (옮김) file 심플디 2014.04.25 1592
» [MFC :: OpenGL] DXF :: Part 4 (옮김) file 심플디 2014.04.25 1490
32 [MFC :: OpenGL] DXF :: Part 3 (옮김) file 심플디 2014.04.25 1466
31 [MFC :: OpenGL] DXF :: Part 2 (옮김) file 심플디 2014.04.25 1523
30 [MFC :: OpenGL] DXF :: Part 1 (옮김) file 심플디 2014.04.25 1566
29 [MFC :: OpenGL] Proposal 및 앞으로의 계획 (옮김) 심플디 2014.04.25 1557