Hatena::ブログ(Diary)

明日とロボット このページをアンテナに追加 RSSフィード

2011-07-12

Collada(.dae)3DモデルをC#とDirextX10で表示

目的

  • C#で、Google SketchUpから得た3Dモデルを表示させたい
    • ダウンロードできる形式は、[.skp]という独自のフォーマットだが、公式ビュワーからxmlベースの[.dae]として出力することが可能。
  • SlimDXというDirectXアプリ開発のためのオープンソースライブラリを用い、SlimDX ColladaLoader libraryで紹介されている方法で、3Dモデルを表示してみる。

使うモノ

手順(基本はこちらで公開されているチュートリアルより)

  • まずはSlimDX SDKをインストール
  • スタートメニュー -> SlimDX SDK -> Samples -> Install Samplesでサンプルを展開
  • こちらからSlimDX-ColladaLoader-1.0.zipをダウンロード、解凍。
  • サンプルモデルをダウンロードし、それぞれを以下のように配置
Folder
 +-ColladaLoader
 +-SampleFramework
 +-SimpleModel10
   +-Effects
   +-Models
   +-...

ColladaLoader

  • ColladaLoaderフォルダ下のColladaLoader.slnをvisual studioで開く
    • (.ump)ファイルがひらけないと出るが、無視。(UMLのデータは使わないので)
    • もし、以下のような警告が出ているようならば、ターゲットに指定された.NETのバージョンを変更
The primary reference "Microsoft.CSharp", which is a framework assembly, could not be resolved in the currently targeted framework. ".NETFramework,Version=v2.0". To resolve this problem, either remove the reference "Microsoft.CSharp" or retarget your application to a framework version which contains "Microsoft.CSharp".	ColladaLoader
...
    • Solution Explorerで、プロジェクト名を右クリックしプロパティー、target frameworkを.Net Framework4に変更
  • referenceでSlimDXがきちんと参照されていない場合は、一端削除し、Add Reference -> Browse でインストール先フォルダ内のdllを参照
    • 例:C:\Program Files (x86)\SlimDX SDK (March 2011)\Bin\net20\x64\SlimDX.dll
  • ビルドしようとすると、バージョンの違いによってか以下のような警告が出た。
Warning	1	'SlimDX.Direct3D10.InputLayout.InputLayout(SlimDX.Direct3D10.Device, SlimDX.Direct3D10.InputElement[], SlimDX.D3DCompiler.ShaderSignature)' is obsolete: 'Use the constructor overload taking a ShaderSignature as the second argument instead.'	C:\3dview\ColladaLoader\Mesh\ColoredMesh.cs	53	23	ColladaLoader
Error	2	The name 'ShaderFlags' does not exist in the current context	C:\3dview\ColladaLoader\Mesh\TexturedMesh.cs	54	95	ColladaLoader
Error	3	The name 'EffectFlags' does not exist in the current context	C:\3dview\ColladaLoader\Mesh\TexturedMesh.cs	54	113	ColladaLoader
Warning	4	'SlimDX.Direct3D10.InputLayout.InputLayout(SlimDX.Direct3D10.Device, SlimDX.Direct3D10.InputElement[], SlimDX.D3DCompiler.ShaderSignature)' is obsolete: 'Use the constructor overload taking a ShaderSignature as the second argument instead.'	C:\3dview\ColladaLoader\Mesh\TexturedMesh.cs	59	23	ColladaLoader
Error	5	The name 'ShaderFlags' does not exist in the current context	C:\3dview\ColladaLoader\Mesh\ColoredMesh.cs	48	94	ColladaLoader
Error	6	The name 'EffectFlags' does not exist in the current context	C:\3dview\ColladaLoader\Mesh\ColoredMesh.cs	48	112	ColladaLoader
  • よって順番に訂正
  • まずは
FLayout = new InputLayout(FDevice, PositionColored.InputElements, FPass.Description.Signature);
  • 新しいバージョンでは、2つめと3つめのargumentが入れ違っているというので、2カ所ともこれらを交換
FLayout = new InputLayout(FDevice, FPass.Description.Signature, PositionColored.InputElements);
  • そして、ColoredMesh.csとTextureMesh.csそれぞれにおいて、SlimDX.D3DCompilerを参照するように追加
using SlimDX.D3DCompiler;
  • Effect.FromFileのargumentも変更が加わったようで、新たに以下が追加されていたため、単純に最後の2つのnullを消す。
Effect Effect.FromFile(Device device, string fileName, string profile, ShadeFlags shaderFlags, EffectFlags effectFlags)
  • これでビルドできた。

SampleFramework

  • 次にSampleFramework下のSampleFramework.csprojを開く
  • Solution Explorerで、プロジェクト名を右クリックしプロパティー、target frameworkを.Net Framework4に変更
  • referenceでエラーが起きてたので先ほどと同様に、SlimDXを一端removeし、add referenceでインストールしたSlimDXを参照
  • ビルドする

SlimDX

  • SimpleModel10下のSimpleModel10.csprojを開く
  • Solution Explorerで、プロジェクト名を右クリックしプロパティー、target frameworkを.Net Framework4に変更
  • 先ほどと同様に、SlimDXの参照先も修正。
  • Sample Frameworkもエラーを起こしていたので、いったん取り除き、先ほどビルドして作ったSampleFramework.dllを参照
    • 例:C:\3dview\SampleFramework\bin\Debug\SampleFramework.dll
  • この状態でビルドして実行してみると、初期のサンプルの木星が表示される。

Collada(.dae)形式の図形の表示

  • サンプルでダウンロードしたモデルは、MeshLabなど、一般の3Dモデルビュワーで見るとこんな感じ。

f:id:astrobot:20110712195444j:image

    • これにdds形式のテクスチャを貼ったイメージを表示する。
  • まず、referenceにcolladaloader.dllを追加する。
    • 例:C:\3dview\ColladaLoader\bin\Debug\colladaloader.dll
  • 次に、SimpleModel10Sample.csを開き、以下のように変更を加える。
  • ColladaLoaderをインポートする
using ColladaLoader;
  • クラスの頭で、ColladaFileを宣言
ColladaFile Test;
  • OnResourceLoad()関数の最後に、以下を追加
CreatePrimaryRenderTarget();

//オリジナルのサンプルとは違い、作者は好みでY-vectorをup vectorとして使うような変更が加わっている。 
view = Matrix.LookAtLH( new Vector3( 0, 0, -10 ), new Vector3( 0, 0, 0 ), Vector3.UnitY ); jupiterMesh.Effect.GetVariableByName( "view" ).AsMatrix().SetMatrix( view );

//ゴブリンの全体が入るように、深さを1000に変更 
proj = Matrix.PerspectiveFovLH( 45.0f, WindowWidth / (float)WindowHeight, 0.1f, 1000.0f ); jupiterMesh.Effect.GetVariableByName( "proj" ).AsMatrix().SetMatrix( proj );

//Collada Fileをインスタンス化し、ファイルからロード。位置を設定し、DirectXデバイスを渡す。
//オブジェクトの位置は、world position*view matrix*projection matrixのようにして指定でき、回転等もかけれる。
Test = new ColladaFile("Goblin", new Vector3(0.0f, -50.0f, 100.0f), Context10.Device); 

Test.SetProjection(proj);
  • onResourceUnload()の最後に以下を追加。
Test.Dispose();
Context10.Device.ClearState();
  • OnRender()の最初の行に以下を
rotation += (float)( Math.PI / 4.0f * FrameDelta );
  • 最後に以下を追加
Context10.Device.OutputMerger.BlendState = transBlendState; 
jupiterMesh.Draw(); 
Test.SetView(view); 
Test.Render();
  • ビルトして実行すると以下のように表示された。

f:id:astrobot:20110712210605j:image

問題点

  • ただ、google 3D warehouseからのファイルをdaeに変換したのだと使えなかった。
    • パースする際に、足りない情報があるみたい。
  • effectも、textureももう少し仕組みを学ばなくちゃ先に進めない。