반응형

COLLADA (I'm saying it with a "ah" at the end), and Assimp (ple as that).

And so, why COLLADA? Simple:

  • COLLADA is an open standard made by Khronos (Sony specifically). The beauty of an open standard format is that it's, well, a standard! You can be assured that any output of a standard-conformant product would also read correctly by another standard-conformant product. Sad to say though, some 3d modelling products aren't that particular in their measures for standards conformance for COLLADA. But still be rest assured: Blender, Maya, 3ds Max and all the other big names in 3d modelling has good support for the format.
  • COLLADA uses XML. This makes it much more simpler for you if your planning to create your own reader or writer.
  • ADDITIONAL: COLLADA is, I think, the only format that is not tied to a specific company. This is a very good thing for us, you know.
  • ADDITIONAL 2: It is known that COLLADA is slow to be parsed. That's true. But think of it: all other non-binary formats (like fbx) have also the same issues. For your needs, COLLADA should suffice.
  • ADDITIONAL 3: COLLADA supports animations!

For the importer library, I highly recommend Assimp. Why?

  • Assimp has support for any popular format you can imagine. It has a unified interface for all formats so that switching to another format is less of a pain.
  • Assimp is extensible. You can thus import your proprietary format and still not modify your code.
  • ADDITIONAL 4: Assimp is open source! Let's support open source software!


http://goo.gl/7VVqD

반응형
반응형

콜라다 홈피
https://collada.org/

콜라다 다운받을 수 있는 주소
https://code.google.com/p/opencollada/




http://wrice.egloos.com/5027746

Collada 소개와 책 추천
제가 Collada 를 공부해야겠다고 생각하게 된 계기는 첫번째로, Gamasutra 에서 구인 광고 할때  Collada 경험자를 선호한다는 것을 몇번 보아왔기 때문이고, 둘째는 PhysX 문서를 읽던중에 Collada 가 몇번 언급 되었기 때문입니다,

생소할수 있는 기술인 Collada 를 한마디로 요약하면, Max/Maya exporter 라고 할수 있겠습니다. 흔히 게임 개발자들이 Max 에서 생성된 데이터를 게임에서 불러와서 화면에 보여주려면 Max 용 plug-in 을 직접 작성해야한다고 알려져 있습니다. 그리고 이 plug-in SDK 를 사용해서 exporter 를 만드는게 쉽지 않습니다. 한국에서 특히 많이 팔린 GameBryo 라는 게임 엔진이 선호되는 많은 이유들 중의 하나가, 안정적인 Max exporter 를 제공하기 때문입니다.

Max/Maya 를 사용해서 파일을 저장할때 binary 파일로 저장을 하게 되면 그걸 읽어서 게임에서 불러 들여서 사용하면 참 행복하겠지만, Max/Maya 내부에서 사용하는 데이터 포멧을 일반 프로그래머들이 이해하기란 시간이 너무 많이 걸리고, 버전이 올라갈때마다 갱신해야한다는 문제점이 있습니다. 그래서 Max/Maya 의 개발자용 SDK 를 사용해서 export 할수 있도록 exporter 를 개발해서 사용하게 되는 것입니다. 그러면 자신의 게임에 필요한 정보만 뽑아내서 외부 파일로 저장하는것이 가능해집니다.

exporter 를 만드는것이 부담되는 경우에 흔히 택하게 되는 차선책은 ASE 파일 포멧입니다. 이것은 사람이 읽을수 있는 형태의 ascii 파일 형태이기 때문에 적절한 파서를 만들어서 사용하기 용이 합니다.

exporter 를 만들지 않을 경우 또 한가지 고려할수 있는 선택지는 .X 파일입니다. Microsoft 에서 개발한 자체 포멧인 X 파일을 사용하면 따로 파서를 만들 필요도 없이 바로 게임에서 사용이 가능하고 LOD 같은 훌륭한 기능도 덤으로 사용할수 있게 됩니다.

그런데 ASE 와 X 파일에는 한계가 있어서, 상용 게임을 개발하고자 할때에는 이 둘중의 어느것도 사용할수가 없습니다. 특히 문제가 되는 것은 "에니메이션"입니다. 게임에서 사용하는 에니메이션은 Skeleton 이라는 데이터 구조를 사용하는 방식인데, 이것을 지원하지 못하기 때문입니다.

에니메이션 이외에도, Occlusion culling 에 사용할수 있는 Scene Graph 지원이 안되고, Physics 연동이 안되어서 게임 프로그래머가 직접 구현을 해주어야 한다는 한계도 있습니다.

Collada 는 이런 문제점들을 모두 개선할 목적으로 개발된 XML 표준안입니다. Max/Maya 에서 Collada 포멧으로 파일을 저장하면 text 형태로 사람이 읽어볼수 있도록 XML 로 저장이 됩니다. 그리고 이렇게 저장된 데이터에는 Geometry 정보, Scene, Animation, Physics 정보등이 모두 포함되어있습니다. 거기에 더해서 Max 에서 저장한 Collada 파일이 Maya 에서도 불러와서 수정할수 있도록 상호호환이 가능합니다.

Collada 는 XML 표준안일 뿐이기 때문에 실체를 갖은 소프트웨어는 없다고 볼수 있겠습니다. 하지만 Collada 를 밀어주고 있는 Sony 에서 Collada DOM 이라는 소프트웨어를 개발해서 제공하고 있고, XML schema 의 문법이 아주 잘 완성되어있기 때문에 이것만으로도 충분히 실용성을 가지고 있다고 할수 있겠습니다.

저는 Collada 검색어로 Amazon 에서 이 책(Collada: Sailing the Gulf of 3d Digital Content Creation)이 검색 되길레 일단 별다른 기대없이 도서관에서 빌렸습니다. 그런데 책이 상당히 좋았고, Collada 에 대한 아무런 배경 지식이 없었는데 많은 것을 얻을수 있었습니다. 사실 Collada 관련 정보는 입수하기가 매우 어려웠고, 입문자를 위한 자료로는 이 책이 거의 유일한것 같습니다. (그래서 그런지 얇은 책임에도 불구하고 비싸게 팔더군요...)

간단히 요약하면 다음과 같습니다.
1장: 소개
Collada 의 개발 배경과 간단한 역사(?)가 설명됩니다.

2장 : Collada Document
Collada 와 XML 표준과의 연관 관계를 설명합니다.

3장 : Collada Geometry
Collada 내부에서 기하 도형을 어떻게 표현하는지 설명합니다.

4장 : Collada Scene
Collada 내부에서 Model 의 Local/World 좌표계 표현을 어떻게 하는지 설명합니다. 그리고 각 node 간의 종속 계층 관계를 어떻게 표현하는지도 설명합니다.

5장 : Collada Effect
Collada 파일 안에 Shader 코드를 어떻게 집어 넣는지 설명합니다. Collada Effect 는 Collada FX 라고 부르기도 합니다. 책의 설명에 따르면 NVidia 에서 개발한 FX Composer 의 표멧과 거의 같다고 하는데, 제가 FX Composer 를 안써봐서 잘 모르겠습니다. DX 에서 사용하는 Effect Framework 의 약간 변형된 형태와 같다고 볼수 있겠습니다.

6장 : Collada Animation
Collada 에서 Skinning 와 Morphing 을 어떻게 표현하는지 설명합니다.

7장 : Collada Physics
Collada 에서 물리를 어떻게 표현하는지 설명합니다. Rigid Body 밖에 아직 지원하지 않는듯 합니다. 대부분의 내용은 PhysX 개발자들의 영향을 받았다고 합니다.

8장 : Collada Contents Pipeline
Collada 의 Conditioner 와 Refinery 의 개념을 설명하고 앞으로 개선 방향을 제시합니다.
책 자체는 매우 작은 헨드북 수준의 책입니다. 뒤의 별 내용없는 부록 부분을 제외하면 160페이지 정도 밖에 되지 않습니다. 저는 읽는데 2일 걸렸습니다.

읽고나서 소감은, 앞으로 조만간 Collada 가 대세가 되겠다는 생각이 들었습니다.

책은 1.4 버전을 기준으로 입문자를 위해서 만들어진 책입니다. Collada 웹 사이트에 가보면 지금 1.5 버전의 표준안이 공개되어있어서 다운 받을수 있습니다. 200 페이지가 넘는 표준안 문서가 공짜로 공개되어있는 상황인데, 그래도 그 표준안은 입문자를 위한 수준이 아니어서 이 책을 먼저 한번 읽어주고 표준안을 보면서 코딩하는게 좋겠다는 생각입니다.

그리고 한편으로는 GameBryo 는 이제 뭘로 먹고 사나 하는 생각이 들었습니다. 물리는 PhysX 구현에 의존하고, 소리는 마일드에 의존하고, 유일하게 강점이었던 SceneGraph 랑 Max Exporter 도 이제 Collada 가 대세가 되면 Collada 에 의존하게 될텐데....;;;

트랙백 주소 : http://wrice.egloos.com/tb/5027746
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
 Tracked from bt22d's me2DAY at 2009/10/07 11:22

제목 : 헌신랑의 생각
쌀밥게임 대왕 : Collada 소개와 책 추천...more

 Commented by 쌀밥 at 2009/08/01 04:14 
AutoDesk 에서 개발한 FBX 라는 파일 포멧도 있군요:
http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=6837478
 Commented by 쌀밥 at 2009/08/01 06:01 
Collada Official Viewer 라는것이 있군요.
http://www.feelingsoftware.com/content/view/40/66
이름이 Feeling Engine 이라고 합니다.. (근데 상용이군요...)

무료도 있는데 제대로 돌아가는지는 모르겠군요.
http://wiki.worldforge.org/wiki/Collada
 Commented by MuMbi준환 at 2009/08/03 16:37  
저도 쌀밥님과 같은 생각입니다. 

현재 취직하기 위해 포트폴리오를 제작하기 위해 exporter 를 제작하려고 자료를 찾아보다가 collada 를 알게 되어 막 개발에 들어갔습니다. 

collada 가 3d model 표준 이라는 말이 가장 많은 매리트였고 
웹 3D 를 구현한 google 이나 flash 3D library 에서도 collada 를 사용한다고 알게 되어 collada 를 사용하여 구현하려고 합니다.

그런데 우리나라에는 collada 에 관련된 자료가 많지 않아 이렇게 검색하다가 블로그에 들리게 되었네요. ^^;

저는 현재 feelingsoftware 에서 제공하는 FCollada library 를 사용하여 개발 중입니다. 

시작부터 삽질이 많네요.

좋은 정보 많이 알아갑니다.

추천 하신 책은 꼭 읽어봐야겠네요. 

즐거운 하루 되세요 ^^
 Commented by MuMbi준환 at 2009/08/03 16:44  
아, 저 책 어디서 빌릴 수 있을까요?
 Commented by 쌀밥 at 2009/08/08 14:32 
책은 생각보다 얆고 괜찮은 편입니다. 좀 비싸기는 하지만 하나 장만하시는게 좋겠다는 생각입니다. 워낙에 보는 사람이 없어서 빌리기가 어렵습니다.

그리고 FCollada 는 안써봐서 잘 모르겠지만 ColladaDOM (공식 라이브러리) 만으로도 충분히 좋다고 생각합니다. SVN 으로 최신버전 (2.2)을 받으시면 제대로 컴파일되고 돌아가는 viewer 로 얻으실수 있습니다. Open source 로 개발되고 계속 업데이트도 되고 있는 중이라서 좋습니다. FCollada 는 업데이트가 중지된지 꽤 된걸로 알고 있습니다.
 Commented by MuMbi준환 at 2009/08/20 09:09  
아 좋은 정보 감사합니다. 

어쩐지 FCollada 는 1.4 버전이 끝이더라구요.. 

ColladaDOM 으로 다시 해야겠네여 ㅎ
 Commented by STL at 2010/01/28 22:33  
좋은 정보 담아가겠습니다~
 Commented by 쌀밥 at 2010/01/29 12:54 
Sony PS3 SDK 설치하니까 Collada XML Loader 도 같이 설치 되더군요...
 Commented by 초보 at 2010/08/24 07:23  
정보감사합니다.
x파일로 포폴만드는중인데 collada 로 만들고싶은 생각이
확듭니다. 그나저나 초보들은 너무힘이듭니다.
이거찔끔저거찔금 하다 시간다가네요.ㅠㅠ
 Commented by 쌀밥 at 2010/08/27 17:43 
회사에서 일하기 시작하면 찔끔 거릴 시간 조차 없는것 같아요...

x 파일도 좋은데 collada 가 x 파일보다 강점인것은 애니메이션을 지원할수 있다는 점입니다. 근데 저도 아직 애니메이션을 지원하는것 까지 구현하질 못했습니다.

물리 엔진을 사용하시면 애니메이션 구현이랑 연동 시키는 부분에서 어떻게 구현할지 정해야할 텐데, 구부분을 잘 고려해보시고 물리엔진만으로 애니메이션이 커버 될것 같으면 그냥 X 파일로 가시는 것도 한가지 방법이겠습니다.

시작하는 초기 단계라면 계획을 너무 무리하게 잡고 시작하는 것은 좋지 않을것 같아요. 게임 프로그래밍은 만만한게 아니니까요 ㅎㅎ
 Commented by 기쿤 at 2011/01/28 14:41  
.x 파일도 skeleton animation을 지원하는거 아닌가요?
그.. tiny.x 도 그럴텐데;;
 Commented by 쌀밥 at 2011/01/31 18:49 
기쿤// 다시 검색해보니 X 파일도 키를 사용한 애니메이션이 되는군요.
http://msdn.microsoft.com/en-us/library/bb172239%28v=vs.85%29.aspx
 Commented at 2012/02/19 08:33  
비공개 덧글입니다.

반응형
반응형

http://developinghappiness.com/?page_id=222


Make 기반 빌드 시스템

차례

예제 파일 다운로드 및 실행

make (버전 3.80 이상), gcc 및 mercurial이 설치된 리눅스에서는, 해당 포스트에서 다룬 내용의 예제 Makefile 및 소스 파일들을 다운로드 받아서 직접 실행해 보실 수 있습니다.

처음으로 다운로드 받을 때에는 hg clone을 사용합니다.

추후 글이 추가되거나 수정되면서, 관련 예제  파일들이 변경된 내용을 업데이트 하고 싶을 때에는, hg pull 명령어를 사용해서 타이핑 횟수를 줄일 수 있습니다.

예제 파일들을 다운로드 받은 이후에는, 해당 Chapter 디렉토리로 이동해서 make의 -f 옵션으로 실행할 Makefile 이름을 지정해서 해당 Makefile로 make를 실행할 수 있습니다. 예를 들어 Chapater3 의 예제 3.4 를 실행하시려면 다음과 같이 하면 됩니다.

Chapter7 부터는 빌드 디렉토리 구조가 정해진 관계로, 빌드하기 전에 $PROJ_ROOT 환경 변수가 올바르게 이루어져 있어야 하기 때문에, 다음과 같이 해 주셔야 합니다. ($PROJ_ROOT 가 설정되지 않은 상태에서 빌드를 실행하면, 빌드에 필요한 공용 include 파일을 찾지 못하겠다는 에러 메지시자 나옵니다.)

Chapter9 부터는 공유 라이브러리가 지원됩니다. 공유 라이브러리를 링킹한 응용 프로그램을 실행할 때에는, 실행 전에 해당 공유 라이브러리가 지정된 디렉토리를 LD_LIBRARY_PATH 환경 변수를 지정해야 합니다. 만약 디버그용(make 실행 시 RELEASE=1 없이 실행)으로 빌드한 경우라면 다음과 같이 설정해 줍니다. (릴리즈용을 실행하는 경우에는 Debug 대신 Release 로 설정해 줍니다.)

 

반응형
반응형

http://developinghappiness.com/?p=26


Make 기반 빌드 시스템 (1): 빌드 시스템?

빌드 시스템?

기본적으로 하나의 프로그램은 수 많은 소스코드들로 이루어져 있고, 규모가 커지면 여러 가지 모듈 또는 라이브러리들로 나누어지게 됩니다. 따라서 작성된 소스 코드로부터 최종 결과물들을 빌드하는데 시간도 많이 걸릴 뿐 아니라, 경우에 따라서는 여러 가지 환경과 옵션에 따라 다르게 빌드할 필요도 생깁니다. 효율적으로 개발하기 위해서는 의존성 관계를 잘 추적해서 그중 일부가 수정되면, 수정된 소스 파일들과, 그 수정으로 인해 변경되어야 하는 소스 파일들만 새로 컴파일 하는 기능도 꼭 필요할 겁니다.

이런 점들을 고려한 통합 개발 환경(Integrated development environment, IDE)은 예전서부터 있어 왔고, 요즘은 정말 훌륭한 툴들이 많이 있습니다. IDE를 사용하면 소스 코드 편집, 빌드, 실행 및 디버깅을 하나의 프로그램 내에서 편리하게 진행할 수 있습니다. 당연히, 의존성에 따라 꼭 필요한 파일들만 다시 빌드 해주는 식으로 빌드 옵션 관리도 똑똑하게 해 줍니다. 심지어는 코드를 수정해서 저장하자 마자, 백그라운드로 빌드해 주기도 하죠.

하지만, 어떤 경우에는 적절한 IDE가 없을 수도 있고, 경우에 따라서는, 예를 들어 일일 자동 빌드를 하는 경우에는, IDE가 오히려 불편할 수 있습니다. 그래서 좋은 개발 도구들은 GUI 기반의 IDE와 함께, 도스나 터미널 같은데서 명령어 기반으로 빌드할 수 있는 기능을 같이 제공하더군요.

그러나 어떤 이유에서였든, GUI 기반의 IDE 없이 개발해야 한다면, 그럼 도대체 어떻게 그런 똑똑하고 효율적인 빌드를 수행할 수 있을까요… 불행히도 없습니다… (응?) 농담입니다. 다행히도, 그런 운 나쁜(?) 개발자들이 의지할 수 있는 친구들이 몇 있는데요, 그 중 하나가 make입니다.

make는 주어진 규칙에 따라 작성된 입력 파일의 내용에 따라 주어진 일을 자동으로 수행하는 유틸리티입니다. 사실 make를 이용해서 여러 가지 작업들을 할 수 있겠습니다만, 소프트웨어 개발자 입장에서 보면 소스 코드를 컴파일하고 링킹해서 최종 결과물을 만드는데 없어서는 안 되는 도구입니다.

참고로 GNU make는 GNU에서 구현한 make이고요, 일반적인 리눅스에는 기본으로 포함되어 있거나 적어도 쉽게 무료로 설치할 수 있습니다. gmake라고도 하죠. 유닉스나 BSD나 기타 다른 OS에서는 gnu make와 다른 make가 있을 수 있는데요, GNU make는 다른 make들에 비해 대부분의 기능 면에서는 문제없이 호환되지만, 자체 확장 기능도 가지고 있습니다. 제 글에서는, 리눅스에서 GNU make를 사용하는 것을 전제로 하기 때문에, GNU make를 그냥 make라고 통칭하도록 하겠습니다.

make에 관련된 가장 훌륭한 레퍼런스는 당연히(?) GNU 사이트의 make 문서입니다.

  • http://www.gnu.org/software/make/manual/make.html: Makefile을 수정하다가, 뭔가 추가로 이런 기능이 있지 않을까? 또는 다른 사람이 작성한 Makefile을 참고하는데 이 내용은 도대체 뭘까? 하는 의문이 들때 결국 찾게 되는 사이트입니다. (단, 영어 실력이 좀 받춰줘야 합니다.)
  • 위 Make 매뉴얼 한글판은 http://www.viper.pe.kr/docs/make-ko/make-ko_toc.html 에 있습니다. (Taehun Kim 님께서 알려 주셨습니다. 아무래도 영어가 부담스러운 사람에게, 위 make 매뉴얼 페이지의 빠르게 내용을 파악하는데 큰 도움이 될 수 있겠네요.

앞으로 쓰는 글에서도 나름 설명하겠지만, make의 기본을 좀 속성(?!)으로 이해하려면, 다음 사이트들의 내용이 큰 도움이 됩니다. 고맙게도 한글로 잘 정리되어 있습니다.

리눅스 쪽 개발 작업에서는 많은 경우 make를 사용합니다. 그리고 생산성과 품질을 중요시하는 제대로 된 개발팀이라면, 다음과 같은 작업이 가능한 빌드 시스템 및 Makefile 파일을 작성하는 고유의 규칙을 가지고 있을 겁니다.

  • 하나의 소스 트리에서 여러 가지 타겟 플랫폼들을 단일 명령으로 빌드할 수 있고,
  • 특정 타겟 별로, 그리고 각 모듈 별로 필요한 빌드 옵션을 적용할 수도 있고, 모든 플랫폼과 모듈들에 동일한 옵션을 한번에 적용할 수도 있으며,
  • 나아가 최종 실행 라이브러리들과 실행파일들을 한방에, 즉 명령어 하나의 입력이나 단축키 하나 누르는 걸로 만들어 내고, 자동화된 단위 테스트(unit test)들을 실행해 낼 수 있습니다.

하지만 늘 해야할 일에 비해 개발인력은 부족한 개발팀에서, 이런 환경을 갖추기란 쉽지 않습니다. 특히나 (제가 주로 몸 담아온 회사들처럼) 규모가 작은 중소기업이라면, 그리고 개발하는 소프트웨어 그 자체로, 돈을 벌어주는 최종 제품이 되는 것이 아니라, 어떤 HW 제품에 내장되는 경우(이를 임베디드 시스템이라 하지요)라면 더더욱 그렇습니다.

일반적으로 뭔가 새 라이브러리나 실행 프로그램을 만들어야 한다면, 그래서 이를 위한 Makefile을 하나 작성해야 한다면, 기존에 존재하는 모듈들의 Makefile 중에서 내가 하려는 것에 가장 비슷한 걸 하나 복사한 다음, 최소한의 수정만 가해서 빌드하는 게 가장 빠르긴 합니다. 하지만 시간이 흐르면서, 모듈들이 많아지고, 요구 조건은 많이 변경됩니다. 하나 둘 컴파일 옵션 추가하는 일도 빈번해집니다. 그때마다 복사해서 사용하던 모든 Makefile들을 똑같이 고치는 단순 반복 노가다를 해야 합니다. 그중의 일부가 누락되면 컴파일 에러가 발생하거나, 운 나쁘면 런타임 에러가 발생합니다. 네, 소스 코드를 복사해서 사용하는 것과 똑같은, 아니 더 심각한 문제가 생기는 거죠.

좋은 환경이 주어지지 않은 걸 한탄만 한다고 달라지지는 건 없습니다. 뭔가 문제가 있다는 인식을 하고 그것을 꼭 해결하겠다는 의지만 있다면, 적어도 효율적인 소프트웨어 빌드 시스템은 만들어 낼 수 있습니다. 이 글은 그런 과정에서의 시행착오를 줄여서 생산적인 개발 작업에 좀더 집중할 수 있게 하고, 소프트웨어 개발자의 삶이 조금이나마 편해지는데 도움이 되었으면 하는 바람에서 쓰여 졌습니다.

사실 요즘은 좋은 빌드 툴들이 여럿 있습니다. 제 개인적으로는 jam 이나 waf 같은 것들을 고민해 봤던 경험이 있습니다. 특히 waf는 제가 좋아하는 python을 이용한 시스템이어서 참 매력적이었지만, 여러 명이 사용해야 하는 환경에서는, 관련된 사람들이 얼마나 쉽게 사용할 수 있어야 하느냐도 무척 중요합니다. 빌드 시스템을 관리하기 위해 새 언어를 배워야 한다라는 걸, 아주 바쁜(!) 여러 사람들한테 설득한다는 것은, 음… 쉽지 않은 일입니다.

그에 비해 Makefile을 작성해서 make로 빌드하는 건, 많은 개발자들, 특히 중요한 역할을 담당하는 경험 많은 개발자들일수록 익숙해져 있기 때문에, 빌드 시스템 구축 및 도입을 비교적 용이하게 할 수 있는 장점이 있습니다. 물론 make도 많은 기능을 가지고 있어서, 어느 정도 쓸 수 있기까지 시간과 노력이 좀 필요하지만, 일단 익숙해지고 나면 개발 과정에서 생기는 여러 가지 돌발 상황을 효과적으로 대응할 수 있습니다. 또한 개발을 진행하다 보면, 이런 저런 이유로 개발팀 외부의 소스 코드나 라이브러리를 활용해야 하는데, 많은 경우 Makefile이 제공되어 make를 이용해서 빌드하도록 되어 있기 때문에, 소프트웨어 개발자로 살아가는데 make를 잘 아는게 언젠가는 도움이 될 겁니다.

이제 그럼 make를 이용해서, “생산성과 품질을 중요시하는데 도움이 되는” 빌드 시스템을 실제로 만들어 보도록 하겠습니다.

 

반응형
반응형

http://cafe.naver.com/apollocation/479

 

 

별거아니지만 혹시나 필요하신분들이 있을까봐 올립니다~

 

 

3dmax에서 작업후 Collada(dae)파일로 export하여 papervision3d에서 사용하는 방법인데요.

 

필요하신분들은 유용하게 쓰시길 바래요~ㅋ

 

일단 collada란 플러그인이 필요한데,

 

http://update.multiverse.net/wiki/index.php/Installing_the_3ds_Max_COLLADA_Plugin

이곳으로 가시면 됩니다.

 

위치는 아래그림에 있답니다~

 





 

 

collada plugin파일을 다운받으셨으면 다음과 같은 경로에 넣습니다~

 

 

 

3dmax가 설치되어있는경로에 plugins란 폴더에 넣으시면 되겠죠.

 

 

그다음,

 

더블클릭~하시면..

 

 

[Next]하시고

 

[I Agree]하시고나면

 

 

이와같은 창이 뜹니다.

 

저는 3ds Max 9.0을 쓰기때문에..

 

 

 

이와같이 체크를 풀어주고

 

[Next] 클릭.!

 

그다음 [Install] 클릭하시면 되요~

 

 

 

아주 잘 되고 있습니다~ㅋ

 

다되면 [Finish] !!

 

 

아까 설치한 경로를 다시 들여다보면

 

ColladaMax.dle란 파일이 생겼죠?

 

저것이 플러그인이란 놈인가 봅니다.

 

그다음 3dMax를 실행해서 직접 Export를 해봐야겠죠.

 

 

 

저는 간단하게 박스를 만들어 봤습니다~

 

Max를 잘하시는 분들은 멋있는걸 만드시겠죠~ㅎㅎ

 

그다음 [File]-[Export] 또는,

          [File]-[Export Selected]를 클릭합니다.

 

 

파일형식을 보다보면 COLLADA(*.DAE)란 놈이 있죠.

 

우리는 저놈으로 Export를 해야합니다~

 

클릭!

 

파일 이름을 입력하시고 저장 하시면!

 

 

이러한 창이 뜨네요.

 

뭐 그냥 이것저것 속성을 보여주는 창 같은데.

 

저는 잘 모르겠네요~그냥 OK버튼 눌러서 하면 멀쩡히 잘 돌아가니까 "OK"합니다~

 

추후에 저거에 대하여 잘 알고계신분들은 글 하나 남겨주시면 정말 감사하겠습니다~

 

그다음 export되어있는 경로를 가보면

 

[파일이름].DAE파일이 생성되어있는걸 보실수 있습니다.

 

정말 간단하죠?

 

필자는 이 파일을 Papervision3d에서 돌리는 작업을 하고 있습니다.

 

MAX파일이 복잡해지면 용량이 커지면서 꽤 느리더군요..

 

공부를 더 많이 해봐야될것 같습니다.

 

처음으로 이런 자료를 올린거라 많이 허접하고 부족하네요;

 

그래도 하루종일 여기저기 물어보고 찾아보고 삽질하며 찾아본 자료랍니다~

 

다음엔 더 유용한 자료를 올릴수 있도록..^^;

 

좋은하루 되시길~

 

 

반응형
반응형

http://blog.naver.com/wonjinho81/90121971442


xerces C++ 오픈 XML 라이브러리 컴파일 

2011/08/30 18:12

복사http://blog.naver.com/wonjinho81/90121971442


libxml2와 xerces를 놓고 개 갈등 하다가 xerces로 결정했다

아래 링크로 가서 이미 컴파일된 바이너리를 받아서 써도되고 소스를 받아서 컴파일해서 써도된다

난 VisualStudio2005로 컴파일 해본다

 

c++용 xerces 3.1.1 버전 소스 다운로드

http://xerces.apache.org/xerces-c/download.cgi

 

 

다운로드 하고 압축을 풀면

xerces-c-3.1.1/projects/Win32/VC8/xerces-all 경로에

xerces-all.sln  솔루션 파일이 있다 컴파일러 종류와 버전별로 솔루션 파일이 다 있어서 편리하다

 

VisualStudio2005로 열어서 솔루션 탐색기를 보면 xerces-all에 포함된 31개 프로젝트가 나타난다

 

프로젝트가 굉장히 많은데 이중에 밑에서 다섯번째 "XercesLib" 프로젝트가 xml 라이브러리이고

나머지 프로젝트는 exe를 생성하는 샘플 소스 프로젝트이다

따라서 "XercesLib" 프로젝트만 빌드하면된다

 

프로젝트 속성 - 구성관리자 - 활성 솔루션 구성.

 

ICU(international components for unicode)는 유니코드와 관련된 것같은데 ICU와 관련된

라이브러리 같은것들을 추가적으로 받아서 설정 해줘야하나보다

골치아프게 생겼으므로 ICU debug/ICU release는 그냥 넘어가고 나중에 유니코드 관련문제가 발생하면 그때 가서보자

(http://site.icu-project.org/ 참조)

 

dll로 만들어 쓰려면 debug/release 를 사용하면 되고

정적 라이브러리로 만들어 쓰려면 Static debug/Static release 를 사용하면 된다

 

 

소스가 있으므로 당연한 얘기겠지만 32비트 64비트 모두 빌드 가능하다

 

 

 

빌드 완료후 xerces-c-3.1.1/Build/Win32/VC8/Debug 에 dll과 임포트 라이브러리가 생성된다.

반응형
반응형


http://cafe.naver.com/sunschool/69




표준 입출력 처리


 

iostream 클래스는 전역적으로 생성되어 사용할 수 있는 4개의 입출력을 처리하는 전역 오브젝트를 제공한다.

 

cin 오브젝트

cin오브젝트는 키보드로 부터 문자를 읽어들인다. 추출연산자 ">>"을 사용한다.

cin >> name >> address;

 

istream_withassaign클래스의 미리 정의된 오브젝트이다. cin전역 오브젝트는 다음과 같이 선언되어 있다.

extern _CRTIMP istream_withassign cin;

 

16진수나 8진수 값을 입력받기위해 조작자(manipulator)을 사용한다.

hex : 16진수로 입력

oct  : 8진수로 입력

dec : 10진수로 입력

ex) cin >> hex >> a >> oct >> b;

cout 오브젝트

화면에 문자를 출력한다. 삽입연산자 "<<"을 사용한다.

cout << "안녕하세요!!!!";

조작자(manipulator)

             endl  : 개행문자를 삽입한후 버퍼를 플러쉬한다.

             ends : 널문자를 삽입한다.

             flush : 출력버퍼를 플러쉬한다.

폭지정

             width() 멤버함수를 호출한다.

             ex)

cout << “%%%%”;

             cout.width(20);

         cout << “100” << endl;

             setw 조작자를 사용한다.

              cout << setw(10) << “This” << setw(10) << “is” << setw(20) << “Test” << endl;

소수점 처리

             부동소수점에 대해서는 기본적으로 6자리까지 표현된다.  소수점 표현방법을 변경하기 위해서는 setprecision 조작자를 사용한다.

cout << setprecision(1) << 100.1234;  // 소수점 이하 한자리만 표시한다.

기본적인 표시법은 과학기술계산용(ios::scientific)표기법을 사용한다. 이러한 표기법을 사용하지 않으려면 “ios::fixed”를 매개변수로 setioflags 조작자를 사용한다.

cout << setiosflags(ios::fixed) << 1000000000 << endl;

 

cerr 오브젝트

표준에러장치(화면)에 에러를 출력한다.(단위버퍼링-한행이 채워질때 이들 정보를 화면에 출력-을 사용한다)

 

clog 오브젝트

표준에러장치(화면)에 에러를 출력한다.(완전한 버퍼링-명확히 플러시될때까지 여러해에 걸쳐 정보를 저장-을 사용한다)

 

 

파일 입출력 처리

파일 입출력을 위해서는 다음과 같은 세가지 종류의 클래스를 사용한다.

ifstream : 입력 파일 스트림 클래스

ofstream : 출력 파일 스트림 클래스

fstream : 입출력 파일 스트림 클래스

 

파일 열기와 닫기

출력파일 열기

ofstram outfile(“test.dat”); 

if(!outfile)                         // if(!outfile.is_open()) 로 점검하여도 된다.

cout << “파일 오픈 에러”;

else

    cout << “파일 정상적으로 오픈 되었습니다”

outfile.close()   // 파일을 닫는다.

 

입력파일열기

Ifstream infile(“read.dat”);  // 이경우 파일이 존재하지 않으면 생성한다. 파일존재하지 않는경우 생성하지 않으려면

If(!infile)                           // ifstream infile(“read.dat”,ios::nocreate) 형식으로 오픈하여야 한다.

cout << “file open error”;

else

cout << “file open successed”;

 

open 멤버함수에 사용되는 열거형 매개변수

ios::binary

이진모드로 파일 열기(기본은 텍스트 모드이다)

ios::app

파일의 끝에 추가한다

ios::ate

처음에는 파일끝에 추가되지만 그 다음부터는 현재 위치에 추가된다.

ios::in

읽기모드로 파일을 연다

ios::out

쓰기모드로 파일을 연다

ios::trunc

이미 파일이 있는경우 내용을 삭제한다

ios::nocreate

파일이 없으면 에러가 발생된다

ios::noreplace

이미 파일이 있으면 에러가 발생된다.

 

파일에 읽고 쓰기

char ch;

char buffer[81];

ifstream inputfile(“read.dat”);

 

inputfile >> ch;   // 파일로부터 한문자 읽어들인다.

inputfile >> buffer  // 공백문자로 구별되는 한단어를 읽어들인다.

ch=inputfile.get();

inputfile.get(ch);

 

inputfile.get(buffer,80);  // 하나의 레코드가 80바이트 이하이면 ‘\n’ 이 나타날 때 까지 데이터를 읽어 buffer에 저장하고 80바이트 이상이면 80바이트까지 읽어서 buffer에 저장한다.

inputfile.getline(buffer,80) // get과 같지만 ‘\n’문자를 읽어는 들이지만 저장하지는 않는다.

 

ofstream outfile(“test.data”);

outfile << buffer << endl;

 

이진 파일에 읽고 쓰기

char buffer[80];

int nCount=80;

ifstream infile(“test.dat”,ios::in|ios::binary);

ofstream outfile(“write.dat”,ios::out|ios::binary);

while(nCount==80)

{

           infile.read(buffer,80);

nCount=infile.gcount();

outfile.write(buffer,80);

if(outfile.rdstat() != ios::goodbit)

             cerr<< “write error!!”;

}

infile.close();

outfile.close();

반응형
반응형

http://yamoe.tistory.com/228




RapidXml 1.13 의 샘플





RapidXml : http://rapidxml.sourceforge.net/

Platform
Compiler
strlen()RapidXmlpugixml 0.3pugxmlTinyXml
Pentium 4
MSVC 8.0
2.5
5.4
7.0
61.7
298.8
Pentium 4
gcc 4.1.1
0.8
6.1
9.5
67.0
413.2
Core 2
MSVC 8.0
1.0
4.5
5.0
24.6
154.8
Core 2
gcc 4.1.1
0.6
4.6
5.4
28.3
229.3
Athlon XP
MSVC 8.0
3.1
7.7
8.0
25.5
182.6
Athlon XP
gcc 4.1.1
0.9
8.2
9.2
33.7
265.2
Pentium 3
MSVC 8.0
2.0
6.3
7.0
30.9
211.9
Pentium 3
gcc 4.1.1
1.0
6.7
8.9
35.3
316.0







[test.xml]


<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root ver="1">
    <entry stop="1">
        <name type="man1">man1</name>
        <content>content1</content>
    </entry>
    <entry step="2">
        <name type="man2">name2</name>
        <content>content2</content>
    </entry>
</root>




[test2.xml]

<?xml version="1.0" encoding="utf-8"?>
<root ver="1">
    <child>child1</child>
</root>




[main.cpp]


#include <string>
#include <vector>
#include <fstream>
#include <iostream>
 
 
#include "rapidxml-1.13\rapidxml.hpp"           // use rapidxml
#include "rapidxml-1.13\rapidxml_print.hpp"     // to wirte file
 
// 노드 출력
void printNode(rapidxml::xml_node<wchar_t>* node)
{
    // print node
    std::wcout << node->name() << L"=" << node->value();
 
    // print attribute
    for( rapidxml::xml_attribute<wchar_t>* attr=node->first_attribute(); attr; attr=attr->next_attribute() )
    {
        std::wcout << L"\t" << attr->name() << L"=" << attr->value();
    }
 
    std::wcout << std::endl;
}
 
// xml 파일 읽기
void ReadXml(std::wstring& filepath)
{
    std::wifstream xmlFile;
    xmlFile.open(filepath.c_str(), std::ios_base::in);
    if (!xmlFile.is_open())
    {
        return;
    }
 
    xmlFile.seekg(0, std::ios::end);    // 마지막 파일 포인터로 이동
    std::wifstream::pos_type size = xmlFile.tellg();        // 파일 크기
    xmlFile.seekg(0);                   // 처음 파일 포인터로 이동
 
    // xml 파일을 vector로 읽음
    std::vector<wchar_t> xmlData((int)size + 1, 0);  
    xmlFile.read(&xmlData.front(), (std::streamsize)size);
    xmlFile.close();
 
    // parsing
    rapidxml::xml_document<wchar_t> doc;
    doc.parse<rapidxml::parse_default>(&xmlData.front());
     
     
    // get root
    rapidxml::xml_node<wchar_t>* root = doc.first_node();
 
    // print root node & attribute
    printNode(root);
 
    // print child node
    for ( rapidxml::xml_node<wchar_t>* item=root->first_node(); item; item=item->next_sibling() )
    {
        printNode(item);
 
        for ( rapidxml::xml_node<wchar_t>* subitem=item->first_node(); subitem; subitem=subitem->next_sibling() )
        {
            printNode(subitem);
        }
         
    }
    doc.clear();
}
 
// xml 파일 저장
void SaveXml(std::wstring& filename)
{
    rapidxml::xml_document<wchar_t> doc;
 
    // append xml declaration
    rapidxml::xml_node<wchar_t>* header = doc.allocate_node(rapidxml::node_declaration);
    header->append_attribute(doc.allocate_attribute(L"version", L"1.0"));
    header->append_attribute(doc.allocate_attribute(L"encoding", L"utf-8"));
    doc.append_node(header);
 
    // append root node
    rapidxml::xml_node<wchar_t>* root = doc.allocate_node(rapidxml::node_element, L"root");
    root->append_attribute(doc.allocate_attribute(L"ver", L"1"));
    doc.append_node(root);
 
    // append child node
    rapidxml::xml_node<wchar_t>* child = doc.allocate_node(rapidxml::node_element, L"child");
    child->value(L"child1");
    root->append_node(child);
 
    std::wstring xmlString;
    rapidxml::print(std::back_inserter(xmlString), doc);
 
    // 문자를 UTF-8로 변환해서 저장해야 하는데
    // 샘플이므로 처리 하지 않아 실제로 ANSI 파일 형식으로 저장됨
    std::wofstream wstream;
    wstream.open(filename.c_str());
    wstream << xmlString;
    wstream.clear();
}
 
int _tmain(int argc, _TCHAR* argv[])
{      
    ReadXml(std::wstring(L"test.xml"));
    SaveXml(std::wstring(L"test2.xml"));
    return 0;
}

반응형
반응형

http://www.gisdeveloper.co.kr/499




[C++] XML 파서, CMarkup 

XML 데이터를 쓰고 읽기 위해서 인터넷을 검색하던 차에 속도를 강점으로 내세우면서 STL 만을 사용하여 플랫폼 이식에도 뛰어난 오픈소스를 찾았는데요. 바로 CMarkup 입니다. 다운로드 사이트는 http://www.firstobject.com/ 이구요. 사용해 보니 XML의 charset도 지원하여 더욱 믿음이 가는 오픈소스였습니다. XML을 처리할 일이 있다면 한번 사용해 보시기 바랍니다.

추후 이 오픈소스를 다시 사용할 때를 대비하여 사용 방법을 정리해 정리차원에서 올려봅니다.

컴파일 시 주의할 사항은... CMarkup은 MFC의 CString와 STL의 string에 대한 문자열 타입을 사용하며 기본적으로 CString을 사용합니다. 플랫폼에 독립적인 구성을 위해서 STL을 사용하는것이 좋기 때문에 전처리에서 MARKUP_STL를 정의해줘야 합니다. 이 전처리 정의는 프로젝트의 속성 페이지에서 해줌으로써 전역적으로 적용되도록 해야 합니다. 아래의 코드는 XML을 쓰는 예제 코드입니다. 윈도우즈 계열의 개발툴인 VS2008로 작성했습니다.




#include "stdafx.h"

#include "../Markup.h"


int _tmain(int argc, _TCHAR* argv[])

{

    CMarkup xml;


    xml.AddElem( "ORDER" );

    xml.AddChildElem( "ITEM" );

    xml.IntoElem();

    xml.AddAttrib("type", "A");

    xml.AddChildElem( "SN", "132487A-J" );

    xml.AddChildElem( "NAME", "crank casing" );

    xml.AddChildElem( "QTY", "1" );

    xml.OutOfElem();


    xml.AddChildElem( "ITEM" );

    xml.IntoElem();

    xml.AddAttrib("type", "C");

    xml.AddChildElem( "SN", "434417F-Y" );

    xml.AddChildElem( "NAME", "kully casing" );

    xml.AddChildElem( "QTY", "2" );

    xml.OutOfElem();


    std::string csXML = xml.GetDoc();


    printf("%s", csXML.c_str());


    return 0;

}


결과는 다음과 같습니다.

사용자 삽입 이미지

AddElement를 통해 엘리먼트를 만들고, 해당 엘리먼트의 자식을 추가하기 위해 AddChildElem을 사용하거나 먼저 IntoElem을 호출한 후 다시 AddElement를 사용합니다.

이제 반대로 위와 같은 XML 데이터를 읽어 보도록 하겠습니다. 먼저 위의 결과를 파일로 저장해 놓고 그 파일을 읽어 데이터를 추출하는 예제를 들어 보겠습니다. 예를 들어... 아이템(ITEM)의 이름(NAME)과 수량(QTY)을 읽어 보도록 하겠습니다. 위의 XML 문자열의 경우 아이템의 개수는 총2개이므로 2개가 검색될 것입니다. 다음이 이 예제와 부합되는 코드입니다.




CMarkup xml;
xml.Load("d:/data.xml");

while ( xml.FindChildElem("ITEM") )
{
    xml.IntoElem();

    xml.FindChildElem( "NAME" );
    std::string csSN = xml.GetChildData();
    xml.FindChildElem( "QTY" );
    int nQty = atoi(xml.GetChildData().c_str());

    xml.OutOfElem();

    printf("%s, %d\n", csSN.c_str(), nQty);
}



먼저 XML 데이터를 가지고 있는 파일을 Load 매서드를 이용해 읽습니다. 다시 반복문을 사용하여 루트 엘리먼트의 자식 ITEM 엘리먼트를 검색하기 위해 FindChildElem을 사용합니다. 그러면 해당되는 자식 엘리먼트가 추출됩니다. 해당되는 자식 엘리먼트의 자식 엘리먼트를 읽기 위해 IntoElem() 함수를 사용한 뒤에 원하는 엘리먼트(NAME, QTY)를 검색하기 위해 FindChildElem을 호출하고 실제로 값을 읽기 위해서 GetChildData 매서드를 호출합니다. 다 읽은 후 OutOfElem()을 호출합니다. 결과는 아래와 같습니다.

사용자 삽입 이미지







 Commented by 산비둘기 at 2009/11/16 12:09  r x
바쁜업무에 시간내서 글들 정리 하시느라 수고가 많으십니다 . 
좋은 정보 얻고 갑니다 . ^^ 
Replied by 김형준 at 2009/11/16 22:55 x
산비둘기님, 별 말씀을요. 제 스스로에게도 큰 도움이 되고 있습니다.
 Commented by DarkKiss at 2010/01/04 16:13  r x
xml parser에 관한 정보를 찾다가 오게되었네요 좋은 정보 얻어갑니다^^ CMarkup 이용해서 xml에서 정보 가져오는 부분 구현해 봐야 겠네요^^ 그럼 새해 복 많이 받으시고 행복한 하루 하루 보내세요^^ 
Replied by 김형준 at 2010/01/04 17:02 x
네, 이 글이 도움이 되시면 좋겠습니다. 새해 복 많이 받으세요~
 Commented by 나무 at 2010/04/24 09:13  r x
좋은 정보 감사합니다...^^ 
Replied by 김형준 at 2010/04/26 15:59 x
댓글 감사드립니다.
 Commented by JHoney at 2010/06/15 23:38  r x
감사합니다 정말 좋은 정보네요 ^-^ 
Replied by 김형준 at 2010/06/16 18:59 x
저 역시 지금도 잘 활용하고 있는 xml 처리 라이브러리입니다. 도움되셨다니 저도 좋네요!
 Commented by 미아 at 2010/07/06 01:06  r x
xml 파싱으로 검색하다가 들어왔습니다.
덕분에 생각보다 쉽게 문제를 해결했어요. 
좋은 정보 감사합니다~~^_^ 
Replied by 김형준 at 2010/07/07 10:16 x
네, 도움되셨다니 좋습니다!
 Commented by 울티 at 2010/08/16 18:30  r x
안녕하세요 해당 강좌를 보고 조금 어설프게라도 따라했는데 잘 되지 않는 부분이 있어서 문의드려요~ 간단하게 작성했는데.. 실행결과는 아무것도 나오질 않네요 ㅠㅠ
CMarkup xml;

xml.AddElem(MCD_T("Test"));
xml.AddChildElem(MCD_T("a"));
xml.IntoElem();
xml.AddAttrib(MCD_T("type"),MCD_T("a"));
xml.AddChildElem(MCD_T("sss"),MCD_T("2344"));
xml.OutOfElem();

std::wstring csXML = xml.GetDoc();

printf("%s",csXML.c_str());

이게 전부인데 아무런 결과가 나오지 않네요; 
아 그리고 저는 문자열 앞에 MCD_T 이걸 꼭 써야 하던데 안쓰면 에러가나더라구요 
어떻게 해야 그냥" " 이런식으로 사용할 수 있나요 ? 
Replied by 김형준 at 2010/08/18 18:42 x
글쎄요.. MCD_T 매크로를 사용은 처음봅니다만.. 프로젝트 속성 중 사용하는 캐릭터를 멀티바이트 모드로 하면.. 단순히 ".." 만으로 될테고.. 유니코드라면.. L".."인가.. 아니면 T".."인가로 하면 될텐데요..
 Commented by 나쁜남자 at 2010/08/20 18:11  r x
많은 도움이 됐습니다. 
Replied by 김형준(Dip2K) at 2010/08/20 18:31 x
댓글, 감사합니다!
 Commented by 굳굳 at 2010/11/07 22:21  r x
정말 간단하군요 ^^ 
Replied by 김형준 at 2010/11/08 21:27 x
도움이 되셨길 바랍니다!
 Commented by 빵집상인 at 2010/11/13 20:56  r x
올ㅋ 유용한데요~?
Load메서드로 로드하려면 *.xml파일만 읽어들일수있는겐가요? 
Replied by 김형준 at 2010/11/16 15:14 x
파일 확장자는 큰 의미가 없고.. 파일 내용이 xml 포맷이면 됩니다.
 Commented by 김진 at 2010/12/08 17:54  r x
각 함수인자가 유니코드로 되어 변환 에러(error C2664)가 나오는데 이는 어떻게 해결해야 할까요? L 붙이면 printf 에서 에러가 발생하는데;;ㄷㄷ 
Replied by 김형준(Dip2K) at 2010/12/09 22:36 x
유니코드 문자에 함수가 따로 존재합니다.. printf인 경우 wprintf 문을 사용하셔야 합니다..
 Commented by 이효진 at 2011/01/05 10:17  r x
XML 검색하다 찾아왔습니다. 좋은 정보 감사합니다 ^^ 종종 찾아오게 될거 같아요 ㅎㅎ 
Replied by 김형준 at 2011/01/05 19:34 x
도움이 되셨다니 저도 기분이 좋습니다. ^^
 Commented by 안병규 at 2011/04/04 13:31  r x
혹시 라이센스 문제는 어떻게 되는건지 알수 있을까요??
CMarkup Parser 파일안에 들어있는 evaluationlicense.txt 이것 읽어봐도 잘 이해가 안가네요;;; 
Replied by 김형준 at 2011/04/06 17:11 x
상용버전에 사용하려면 구입하라는 의미인듯한데요..
 Commented by 한창영 at 2011/04/13 10:28  r x
CMarkup은 push-pop 구조라서 프로그래밍하기가 수월해서 좋더군요. 다만, 제가 필요하던 주요기능들은 모두 사용버젼에서만 지원하더라구요. 여하튼 주어진 함수들로 필요한 기능은 구현했는데 한가지 아쉬운 것은 indentation 기능이었습니다. 그래서, 다음과 같이 다른 클래스를 사용해서 저장만 하고 있습니다. 참조하세요.
CXml myXML;
myXML.LoadXml( (LPCTSTR) m_strXML );
myXML.SaveWithFormatted(lpszPathName, _T("UTF-8") ); ///default is UTF-8
myXML.Close(); 



반응형
반응형

http://blog.naver.com/patori/90033021950




 

그동안 미뤘던 애니메이션 공부를 다시 하게 됐다.

 

DirectX에서 지원하는 함수로 X파일을 그냥 로드하려고 했는데,

예제 Sample이 훨 어렵다. MS사에서 진정 이걸보고 예제로 쓰라는건지가 의심스럽다.. 

 

어쨌든 일단 예전에 봤던 김용준님의 저서 3D 게임 프로그래밍에서 봤던 xml부터 다시 공부하기로 했다.

xml 코드가 보기도 쉽고 체계적으로 잘 되어 있어서 포맷 공부하기엔 딱인듯 하다.

나중에 MaxScript를 만질 기회가 생긴다면 포맷도 새로 만들수도 있겠다. (먼산) 

 

------------------------------------------------------------------------------------------------------

 

<Body>에서 <Info>, <Material>, <Object>로 크게 갈라진다.

<Info>: 최초로 읽어 들일 때, 전체적으로 가지고 있는 기본 정보가 들어있다.

<Material>: 메터리얼 정보를 가지고 있다.

<Object>: 메쉬와 본, 바이패드 등의 상세 정보를 담고 있다.

 

 

<Info>

 

일단 Info의 정보를 살펴보면 위에서부터 차례대로,

파일이름, 오브젝트 수, 메쉬 수, 애니메이션 프레임 크기, 키 타입, <Object>, <Bone>이 있다.

여기서 오브젝트 수는 <Object>의 총 개수이겠거니 했는데, 정확히 맞지 않는다.

나중에 파싱할 때 이부분은 다시 교체한다.

<info>에서  접혀진 부분에는 이런 값이 들어있다.

 

 

<Bone>에서 BoneID와 ID가 있는데 BonID는 뼈대 개수만큼 있고,

ID는 해당 본의 실제 Object ID를 말한다.

위의 그림에서  BoneID가 1인 Bip01은 Object ID가 7이라는 것을 알 수 있다.

 

여기까지가 <info> 부분이다.

 

 

<Material>

 

메터리얼은 텍스쳐, 광원 등의 재질 정보다.

 

 

<Material>의 개수는 <Slot>의 Index 최종값+1이다.

<Slot>안에서 Material에 대한 정보를 기록한다.

<Diffuse><Ambient><Specular><Emissive><Opacity><Power>는 필수 정보이고,

그 이후의 <DiffuseMap><NormalMap><BumpMap>은 사용된 텍스쳐 종류에 따라 추가된다.

 

 

<Object>

 

가장 데이터 양이 많은 Object부분이다.

해당 Object에 해당하는 모든 정보를 저장하고 있다.

 

 

일단 여기서 Class를 유심히 보아야 한다. 이 Class는 3ds Max에서 이미 정해진 클래스이다.

Class의 종류는 4가지 이다.

 

 

 

Dummy : 더미 클래스로  아무 일도 안하지만, 바운딩 박스와, 위치 정보를 가지고 있다.

              계층적으로 본과 바이패드를 분리할 때, 각각의 계층을 대표하는 정보를 가지고 있다.

Editable_mesh : 메쉬에 해당하는 부분으로 메쉬를 표현하기 위한 모든 정보가 들어있다.

 

Dummy + Editable_mesh 수가 <Info>의 MeshCount 수와 같다.

 

BoneGeometry : Bone에 대한 정보를 가지고 있다.

Biped_Object : 바이패드 정보를 가지고 있다.

이 두 클래스는 상당히 유사하다.

 

클래스별로 세부 내용이 다르고, 그 중 Editable_mesh 와 BonGeometry & Biped_Object 로 크게 분류할 수 있다.

 

Editable_mesh

 

 

여러 섹션중에 가장 많은 정보를 담고 있다.

Parent, Local, World, BoundingBox는 4클래스 모두 공통으로 가지고 있다.

Parent는 계층분류에 사용되고 Editable_mesh에서는 -1(부모를 소유하지 않음)로 설정된다.

그 아래 부분부터가 Editable_mesh의 고유 영역이다.

 

<Vertex> : 버텍스 좌표를 담고 있다.

 

<VertexNormal> : 법선 벡터

 

<TriIndex> : 삼각형 Index 정보를 가지고 있고, index 번호는

                 <Vertex> 안에서 지정된 Index가 사용된다.

 

하나의 메쉬 안에서 여러개의 Material을 설정할 수 있다.

TriIndex의 MaterialCount는 Material의 개수를 담고 있는데,

나중에 파싱할 때에는 하나의 메쉬에 하나의 재질만 가질 수 있도록 분할하는 작업을 하게 된다.

그래야지 나중에 출력 루프가 간편해진다.

일단 여기서는 해당 2번 재질이 사용된 것을 알 수 있다.

 

<TexVertex> : 인덱스 u,v 좌표를 담고 있다.

<TexIndex>  : <TriIndex>와 비슷한 형식으로 대신 TexVertex에서 지정한 인덱스를 기준으로 지정된다.

 

<VertexWeight> : 스키닝에 필요한 각각의 정점 가중치를 지정한다.

 

BoneCount는 해당 Mesh가 스키닝을 위해 참조하는 뼈대의 개수를 저장하고

Vertex를 Index순으로 차례대로 나열하면서 관련된 뼈대의 ID와 가중치를 저장한다. 

 

 

하나의 Vertex당 뼈대는 최대 4개까지 지정할 수 있다.

나중에 계산을 할 때

VResult = VLocal * ( MSkinning0 * MWeight0 + ... + MSkinning3 * MWeight3)  

이런 식으로 계산을 하게 되는데, 관련된 뼈대 개수가 많아지면 행렬 연산이 상당히 많아지므로

최대 4개까지로 지정해 두었다. Bone에서 MSkinning을 구하는 과정까지의 행렬계산 부분도 많기 때문에

어쩔수 없다.

(팔레트 테이블을 사용하거나 버텍스 셰이더를 사용하면 GPU에서 계산을 처리하게 되서 속도를 향상시킬 수 있다.)

 

가중치는 합이 1.0이 되고, 필요에 따라서는 클 수도 있다.

 

BonGeometry & Biped_Object

 

본과 바이패드는 애니메이션에 관한 정보를 담고 있다.

 

 

부모 ID에서 상위 계층 ID를 지정하게되고 나중에 Animation 변환 행렬을 설정할 때

부모의 최종 변환 행렬을 곱해서 최종 Animation 변환 행렬을 구할 수 있다.

 

<Key>안에는 3가지 섹션이 있다.

 

<Position> : 지정된 프레임의 순간 위치 좌표가 설정된다.

 

<Quaternion> : 프레임당 회전량을 쿼터니온으로 표현하였다.

                      쿼터니온은 이전에 기록된 프레임(5frame경우는 0frame)이후의 상대값으로

                      저장되기 때문에 파싱후에는 차례대로 누적을 해서 값을 갱신시켜줘야 한다.

 

<Scale > : 확대/ 축소 비율을 나타낸다.

 

 

------------------------------------------------------------------------------------------------------

 

이렇게해서 기본적인 xml분석은 오와리!

 

반응형
반응형

<MSXML> VC++에서 MSXML 사용법 | XML
오랜만에 다시 강의를 시작합니다. *^^*

MSXML의 개요만 설명하고, VB와 VC++에서 사용법 예제를 지난 강의에 넣었습니다.

지금 다시보니 VB는 잘 되는 것 같은데, VC++에서는 dll의 포함여부에 따라 제대로 동작하기도 하고, 안하기도 하는 것 같습니다.

그래서 이 부분을 한번 정리해 보려고 합니다.


실제로 MSXML의 쓰임새는 VB가 더 많을 것이라고 생각합니다. ASP를 이용해 웹에서도 쓸 수 있고, 자바스크립트에서도 활용하고 있으니까요.

그러나 C/S 프로그램이나 XML관련 애플리케이션을 VC++로 개발하는 경우, 처음 msxml을 사용하려면 어려움을 겪는 분들이 간혹 있습니다.

특히, 저처럼 COM에 대한 개념이 생소한 분들이 그렇지요..

CoInitialze나 CoCreateInstance.. 이런 함수들이 튀어 나오면 그 순간.. 아주 답답해지죠..

실은 저도 COM에 대해서는 잘 모릅니다. 물론 위의 함수의 정확한 의미도 설명할 정도의 수준은 아니고요..

BUT, MSXML을 사용하기 위한 방법에 대해서는 한번 설명해 보려고 합니다.

VB는 MSDN에 나와있는 예제만 참고해도 잘 활용할 수는 있으니.. VC++을 먼저 알아보죠..

음.. 데브피아나 이런데 가면 좋은 MSXML을 위한 wrapper 클래스들이 많이 있을 테니.. 그걸 사용하셔도 되구요..
(저도 이 강의를 끝내면서 library 하나 만들어 볼까 합니다. 나름대로 편리하게 구성해서.. 쩝~ 생각만... 할려나.. 에궁)

필요작업

일단, VC++을 작업하기 위해서 필요한 것부터 간단히 정리해 보죠..

1. 플랫폼 SDK라는 것 들어봤죠.. 이걸 먼저 설치해야 합니다.
요즘 Visual C++로 개발하는데, 이게 없으면 안되는 게 너무 많더군요.. 한번 설치해 두는 것도 괜찮을 것 같네요..

MS의 사이트 주소는 맨날 바뀌니.. 그렇더라도 현재 다운로드 할 수 있는 주소를 하나 적어놓을께요..

http://www.microsoft.com/msdownload/platformsdk/sdkupdate/default.htm

플랫폼 SDK를 설치하는 이유는 여기에 <msxml2.h>라는 헤더 파일이 있기 때문입니다.

2. VC++의 환경설정에서 플랫폼 SDK를 지정해 줘야 합니다.

뭐.. 대부분은 잘 아시겠지만, 혹여라도 잘 모르시는 분이 계실까봐~~

[Tools] - [Options] - [Directories]로 가셔서..

Inclue files 와 Library files에 플랫폼 SDK의 Include와 Lib를 지정하시면 됩니다.

이때, 플랫폼 SDK의 Include와 Lib를 가장 위로 올려놓는게 좋기는 합니다.

3. MFC를 사용하는 프로그램이라면, stdafx.h란 파일이 존재할 겁니다.

여기에 다음과 같은 소스를 아래부분에 추가합니다.

만약 stdafx.h가 없다면.. MSXML을 사용할 헤더나 소스 파일에 이걸 추가하면 됩니다.

#include <MSXML2.H>
#pragma comment (lib, "msxml2.lib")

자.. 이렇게 하면 이제 MSXML을 사용할 준비가 된 것입니다. 그럼.. 시작해 볼까요..

MSXML 이해

MSXML 도움말을 살펴보면 Node나 Attribute를 선언할 때, 변수명이 특이합니다.

이것은 MSXML자체가 DOM 스펙을 따르면서 COM형태로 개발되었기 때문인것 같습니다.

IXMLDOMNode, IXMLDOMAttribute, IXMLDOMDocument

뭔가 공통점이 있죠?

I - 인터페이스를 의미하는 것 같네요
XML - XML이라는 거죠.. 당연한 거죠.. 쩝~
DOM - DOM 스펙을 따른다는 이야기고..
나머지 - 각각의 의미를 나타내고 있죠..

그럼 자주 사용하는 몇가지 변수명만 설명할께요..

IXMLDOMDocument - XML 문서의 최상위 객체입니다. 다른 XML 객체는 여기에서부터 파생된다고 볼 수 있습니다.
IXMLDOMNode - XML의 각각의 Node를 가리키는 객체입니다. DOM의 가장 기본 요소입니다.
IXMLDOMAttribute - Node의 속성을 나타내는 객체입니다.
IXMLDOMElement - XML의 요소(Element)를 나타내는 객체입니다. 실제로 사용할 때는 Node를 더 많이 쓰는 것 같습니다. 요것 보다는
IXMLDOMNodeList - 주로 자식 노드의 리스트, XPath를 이용해 검색한 노드들의 리스트를 가리는 겁니다.
IXMLDOMNamedNodeMap - 주로 속성들의 리스트를 나타낼 때 사용합니다. NodeList와의 구분은 순서가 중요하냐의 여부에 달려있죠..

이외에도 IXMLDOMComment, IXMLDOMProcessInstruction.. 등이 있는데..
앞의 강좌인 XML 기본 강좌를 읽어보신 분은 대략 이해할 수 있을 거라 생각합니다.

이제 본격적으로 코딩을 해봅시다.

프로젝트는 알아서 만드시고.. 주요부분만 한번 해보도록 하겠습니다.

소스를 간결하게 하기 위해서 에러 처리부분은 생략했습니다.
에러가 포함된 소스는 자료실에서 다운로드 받으시면 됩니다.

그리고 여기에는 COM관련 함수들이 많이 나옵니다.
제가 COM을 잘 모르기 때문에 자세한 설명을 할 수가 없습니다. 혹, COM에 대해 잘 아시는 분이 계시면 코멘트를 달아서 설명해 주시면 고맙겠습니다.

MSXML을 사용하기 위해서 먼저 CoInitialize(NULL)를 실행해야 합니다.
그리고 메모리 해제를 위해 끝나면 CoUninitialize()를 하면 되겠죠..

이건 COM 객체를 사용하기 위해 기본적으로 사용하는 것 같습니다.

CoInitialize(NULL);

... // 이 사이에서 msxml을 활용하면 됩니다.

CoUninitialize();

CoInitialize나 CoUninitialize는 만약 클래스로 만든다면 생성자나 소멸자에 넣어도 되겠죠..

그럼 중간에서 XML을 사용하기 위해서는 XML의 기본 객체를 만들어야겠죠.. 바로 IXMLDOMDocument 입니다.

IXMLDOMDocument* m_pXml;

그리고 나서 인스턴스를 생성합니다.

CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&m_pXml);

이렇게 하면 xml 객체를 활용할 수 있게 됩니다. 바로 m_pXml을 통해서죠...

CoCreateInstance를 살펴보면,
Co - COM 관련 함수라는 의미 같은데요.. Cowork인가? 쩝~~ 암튼 그렇구요..
CreateInstance - 인스턴스를 생성하는 것이죠.. 객체지향 프로그램에서는 객체나 클래스, 인터페이스를 사용할 수 있도록 하기 위해서는 그것의 인스턴스를 생성해야 하죠..

여기까지 소스를 종합해보면 다음과 같습니다.

CoInitialize(NULL);

IXMLDOMDocument* m_pXml;
CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&m_pXml);

// 필요한 작업을 수행합니다.

CoUninitialize();


그럼 이번 강좌에서는 XML 문서를 가져오는 것만 해보도록 하죠..
XML 문서는 XML 기초강좌에서 사용한 것을 활용하겠습니다.

MSDN에서 IXMLDOMDocument의 load 함수를 살펴보겠슴다.
XML 문서를 로드할 경우, 파일에서 로드하는 경우와 XML 문자열을 로드하는 경우가 있습니다.
일반적으로 XML 문자열을 로드하기 보다는 파일을 로드하는 경우가 많다고 생각되므로 파일 로드에 대해서 자세히 설명하도록 할께요.

HRESULT load(
VARIANT varXmlSource,
VARIANT_BOOL* varIsSuccessful
);

함수 원형은 위와 같습니다.
VARIANT라는 것이 나오는데요.. 이건 각각의 형별로 union으로 선언한 것이라고 생각하면됩니다.
그러니까 "가변형"이라고 생각하면 되겠네요..

VARIANT varXmlSource는 XML 파일명을 가리키는 것이고요
VARIANT_BOOL* varIsSuccessful 성공 여부를 가리키는 것입니다.

그럼 한번 적용해 볼까요?

CoInitialize(NULL);

IXMLDOMDocument* m_pXml;
CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&m_pXml);

// 파일명을 지정합니다.
variant_t file("test.xml");
VARIANT_BOOL bLoad;

// 파일을 오픈합니다.
HRESULT hr;
hr = m_pXml->load(file, bLoad);
if (FAILED(hr)) return;

if (bLoad) {
// 성공
}

CoUninitialize();

이런형태로 사용할 수 있습니다.
VARIANT 구조체에 맞추어 문자열을 변환하기 위해서 variant_t를 사용했네요..
이걸 사용하기 위해서는

#include <comdef.h>를 포함해야 합니다.

그리고 HRESULT라는 리턴값을 사용했습니다.

typedef LONG HRESULT;

MSDN에 보면 이렇게 선언되어 있는데요. 결과를 알려주는 것입니다.
정확하게 S_OK, S_FALSE, S_INVALIDARG로 리턴이 되는데..

성공과 실패여부를 확인하기 위해
SUCCEEDED(hr) 또는 FAILED(hr) 이렇게 사용할 수 있네요.

자.. 이번에는 읽은 XML 문서의 내용을 화면에 출력하는 부분을 해보도록 하겠습니다.

HRESULT get_xml(
BSTR *xmlstring);


여기에서는 BSTR을 사용하는 방법을 잘 살펴보시면 될 것 같습니다.

if (bLoad) {
BSTR bstr;
CString strValue;

// XML 내용 가져오기
m_pXml->get_xml(&bstr);

// BSTR 변환
USES_CONVERSION;
strValue.Format("%s", W2A(bstr));
SysFreeString(bstr);

// 화면 출력
printf("%s\n", strValue);
}

USES_CONVERSION이나 W2A와 같은 것을 사용하기 위해서는

#include <atlconv.h>를 포함해야 함니다.

BSTR을 CString으로 변경하기 위해 위와 같은 방식을 사용했네요..
그냥 Casting을 해도 결과를 보는데는 문제가 없지만, 메모리 누수를 막기위해 저렇게 사용했습니다.

물론 위와 같은 방식이 아니라 VB와 같이 쉽게 VC++을 사용하는 방법이 있기는 합니다만,
전 이방식으로 쭉 설명할 계획입니다.

경우에 따라서는 필요하기 때문이죠.. C++에 대해서 잘 모르시는 분들은 좀 어렵게 느꼈을 것 같네요..
그래도 한번 따라해 보세요.. 한번의 실습이 열번 읽는 것보다 훨씬 나으니까요..

전체 소스를 한번 정리하겠습니다. 자료실에도 이와 관련된 소스를 넣어둘께요..

그럼.. 좋은 하루 되세요~~ 2005/03/29 미니


if (!SUCCEEDED(CoInitialize(NULL))) return 0;

// Instance 생성
IXMLDOMDocument* m_pXml;
if (!SUCCEEDED(CoCreateInstance(CLSID_DOMDocument, NULL,
CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&m_pXml))) {
CoUninitialize();
return 0;
}

// XML 파일 읽어오기
variant_t file("test.xml");
VARIANT_BOOL bLoad;
HRESULT hr;

hr = m_pXml->load(file, &bLoad);
if (FAILED(hr)) {
CoUninitialize();
return 0;
}

// XML 내용 출력
if (bLoad) {
BSTR bstr;
CString strValue;

// XML 내용 가져오기
hr = m_pXml->get_xml(&bstr);
if (SUCCEEDED(hr)) {
// BSTR 변환
USES_CONVERSION;
strValue.Format("%s", W2A(bstr));
SysFreeString(bstr);

// 화면 출력
printf("%s\n", strValue);
}
}

CoUninitialize();

반응형

+ Recent posts