맥스 플러그인 디버깅 그 두번째 시간

(…사실은 한번에 진행되었던거지만 -ㅂ-)

지난 글에 이은 야그.

대략적인 상황 설명을 세원옹에게 마친 뒤, 디버거를 돌리는 작업으로 돌입.

일단 컴터상엔 작업중인 FaceMarker 와 비교 대상인 Mesh Select 프로젝트를 켜 놓은 비졀스튜됴 외에도, 참고가 될만한 다른 프로젝트 파일들도 수없이 불러놓은 상태. 비졀스튜됴 인스턴스만 한 여섯개는 되었던듯하다-ㅂ-;;

여튼 처음 작업으론, 정상적인 동작을 보이고 있는 Mesh Select 의 코드를 최대한 FaceMarker 와 비슷하게 맞추어, 비정상 동작이 하는 순간을 잡아내자는 것.

..하지만 몇번 코드를 옮겨보아도 잘 동작하고 있는 Mesh Select 이놈을 엉뚱하게 움직이도록 만드는 것은 어렵다고 판단.

그렇다면 이번에는 FaceMarker 의 코드에다 Mesh Select 의 코드를 ‘복사’해 넣어서, 바뀌는 시점을 캐치하자는 방향으로 접근.

우선은 코드의 배열, MAX system API 호출 순서 등을 맞춰보았으나 역시나 문제의 부분은 오리무중..

그래서 이번엔, 아예 FaceMarker 특유의 기능 부분은 주석 처리하고, Mesh Select 의 코드를 갖다가 복사해 넣는 식으로 작업이 진행되었심..

…허나… 역시나 FaceMarker 는 face select 모드에서 선택된 face 를 출력하지 못하고 있는 상황이 반복되고..

어차피 플러그인이라는게 메인 루틴이 되는 MAX 측에서 필요할때 호출하는 함수들로 이뤄진 놈이니 코드의 전체 흐름을 디버거로 보기는 어려운 상황..

혹시 ‘이 함수는 아닐거야..’라고 생각해 제쳐두고 있을지 모르는 함수가 있을까 하여 제안된 방안은 ‘FaceMarker 의 모든 메소드 시작점에 브레이크포인트를 걸어보자!’

…..그렇지만 역시 이 방법도 좌절.. 예상했던 함수 외에 다른 용도로 호출되는 녀석은 없더라는 것.

이에 비장의 카드로 어셈블리 레벨 디버깅을 제안하는 세원옹!
옆에서 덜덜덜 떨면서 그러하시지요라고 대답하는 본인. (…어렵잖아!)

하지만 알지못할 MOV ADD JMP LEA CALL 들 사이를 수십수백번은 헤매야할거라 지레 겁먹었던것과는 달리..

트레이싱을 몇번 거치다 보니.. 어라? FaceMarker 코드를 호출하는 부분이 나오네..?

어랏..근데.. CPP 파일이 아니라 H 파일에 포함된 메소드!!
Modifier::ChannelsChanged() 였던 것이었던 것이었다.

이 메소드의 역할은 modifier 가 변화시키는 데이터 채널을 맥스에게 알려주는 것이다.

순간 ‘띵~’하면서 머리속을 지나가는 무언가 ‘…범인은 이녀석인가!’
하지만 이미 수십..까진 아니고 몇번을 그런 느낌을 받고 실패했던터라 아직까진 반신반의 상태..

여하튼 百見이 不如一打라.. 코드를 고치고 컴파일.. 맥스 띄우고 박스 만들고 edit mesh 건 다음 FaceMarker 적용.. face select..

“된다!!!!!!!!!!!!!!!! ;ㅁ;”

…… FaceMarker 의 역할이 mesh 데이터 자체에 ‘변경’을 가하는 것은 아니기에 이 함수를 들여다 볼 생각은 까맣게 잊고 있었던것.(PART_SELECT 라는 채널이 엄연히 존재하는데도 말이지)

바로 위에 오는 Modifier::ChannelsUsed() 은 작업 중에 손을 본 적도 있었는데.. 이 함수를 건드릴 생각을 못했던건.. 뭔가 씌었거나.. 그랴. 나의 불찰이다 ;ㅁ;

하지만.. face selection 은 일시적인 변경값인데 이것을 mesh data channel 의 하나로서 geometry 정보나 topology 정보와 동급으로 취급된다는건.. 어찌보면 설계할때 개념을 잘못 잡은거라고!! (..라는 식으로 책임회피.. 하지만 소용없다 lllorz )

여하간에.. 바로 위에 모든 메소드에 브레이크포인트를 찍어보자고 할 때에 걸릴번도 했던 이 녀석은..

거주지가 CPP 파일이 아니라 H 파일인지라 깜빡하고 넘어갔던 터에.. 디스어셈블까지 걸어보는 상황에서야 겨우 잡혀주시고 만 것.

테스트하느라 파엎은 코드들을 정리하는 작업까지만 가뿐히 마치고 갈까 했으나..

이미 야심한 시각. 숙소까지 느린 걸음으로도 10분이면 되는 나는 그렇다 쳐도 집까지 30분 차까지 끊긴 시간의 세원옹을 위해서라도 1분이라도 일찍 일어나야 한다!!

…..네..사실은 고치고나니 맥이 빠져서 귀찮아진거예요 ;ㅁ;

여튼 그렇게 그날의 디버깅세션은 막을 내리고..

집에가던 중 갈림길에서 본인은 세원옹에게 감사의 한마디를 건넨 것으로 오늘의 얘기는 끝이납니다.

.
.
.
앗!! 생각해보니 세원옹한테 맛난것 대접하기로 해놓고는 깜빡하고 있었다!! 쏘리 세원옹.

ps. 디버깅작업과는 직접적인 관계없지만, MAX 플러그인 관련하여 메모 몇가지.

1. modifier 에 의해 변경되는 mesh 의 출력은 각 modifier context 에 속한 mesh 가 아니라, 제일 밑단의 object 가 들고 있는 mesh 이다. modifier 들은 이 mesh 를 출력에 맞도록 변화시켜 줄 의무가 있다.

2. 하지만 각 modifier data 클래스는 이 mesh 들에 대한 사본을 가지고 유지할 필요가 있다. 이건.. 왜그랬더라? ;ㅁ; 까먹었네.. 일찍 좀 정리할걸..
여하튼 modifier data 클래스의 mesh 사본의 동기화는 Modifier::ModifyObject() 메소드에서 해 주면 된다.

3. face selection 의 출력 역시 원본 mesh 상의 selection data 에 값을 반영해주면 될 듯 하지만.. 이게 심히 fake 임. 원본 mesh 의 face selection bit array 에 값을 백날 때려넣어도 출력 안됨. 이는 Mesh::render() 메소드에는 face selection 을 출력하는 부분이 구현되어있지 않기 때문이다.(Modifier 에서 구현된건가 그럼..? 정확히 모르겠네 지금으로선) 여하튼, Modifier::ChannelsChanged() 의 반환값 중에 PART_SELECT 플래그가 확실히 세팅이 되어있어야 적용이 된다.

4. Mesh 클래스의 인스턴스를 마련하고, Mesh::render() 함수를 호출하는것만으로 뷰포트상에 임의 mesh 를 출력할 수 있다. 그러나, Mesh 클래스 인스턴스를 생성하는것만으로 무조건 뷰포트상에 렌더링이 걸리게 되는 것은 아니다. Display() 메소드 를 가진 녀석 내부에서 Mesh::render() 를 호출한다던가 하는 식으로 렌더링 메소드를 명시적으로 호출해줘야한다.

날림으로 적었더니 내용은 개발새발.. 다른사람들은 알아먹기도 힘들 말을 적어놨고..

괜찮아. 나중에 나만 알아볼수 있음 돼….
(…과연 알아 볼수나 있겠니? -ㅂ-; )

4 thoughts on “맥스 플러그인 디버깅 그 두번째 시간”

  1. 열혈옹// 고달픈 플러그인 프로그래밍의 세계~

    최강남// 그르흐다! 그를 사무실에서 더 이상 볼 수 없다는 사실에 안습.

ppuchuu에게 댓글 남기기 댓글 취소

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다