Direcx一般都是用VC++開發環境,而c#相關的資料比較少,最近做的一個項目中需要用到一個3D模型,而開發環境是visual c#,沒辦法,就四處搜集資料,尋找相關的資料,然後找到了幾篇相關的博文,不過這些博文說的都不太仔細,有些內容又丟失了一些關鍵代碼,這個時候就需要我們自己搜集資料,自己學習來補全這些關鍵代碼了。
廢話少說,我們直接說說步驟吧。
一.首先要準備一個3D模型,現在3D模型都是.max或者.obj或者別的格式的,不過因為我用的是Directx9.0開發環境,因此載入3D模型的時候需要把檔案轉換為.X格式,沒有關係,我們可以下載一個3dsMax軟體,然後裝上微軟的panda外掛程式,這個軟體就能把.max格式的3d檔案轉換為.x格式輸出。這一步我們最主要的目的就是為了得到一個.x格式的3D模型。
二.接下來就是下載Directx9.0Sdk了,下載完成之後安裝這個開發工具。
三.接下來進入項目,建立一個Visual c# winform表單程式,然後點擊確定,我們的編程工作就開始了。
首先,項目需要用到Directx開發包,因此我們需要給項目添加引用,按右鍵項目,選擇添加引用,然後在引用的對話方塊中選擇瀏覽,這裡引用的位置是:C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0,注意最後的應用的檔案夾是1.0.2902.0,我們引用這裡面的三個檔案:DirectX.dll ,DirectX3D.dll 和DirectX3DX.dll,選擇這三項之後點擊確定,之後就添加了引用,然後我們還需要在表單代碼中添加如下引用:
using Microsoft.DirectX;using Microsoft.DirectX.Direct3D;
之後我們的引用工作算是完成了。
因為我準備把3D模型顯示在一個控制項上,我選擇了一個Panel控制項放到主視窗上,我們的模型待會兒就會顯示在這個panel上。首先在Form中設定如下幾個全域變數:
#region //儲存3D檔案 private Mesh mesh = null; //裝置 private Device device = null; //材質 private Material[] meshMaterials;private Texture[] meshTextures; //擷取當前程式的Debug路徑 string path = System.Windows.Forms.Application.StartupPath; //角度 private float angle = 0.0f; #endregion
然後寫出我們的初始化圖形裝置的函數:
<span style="font-size:14px;"> //初始化圖形裝置 public void InitializeGraphics() { //設定變數 PresentParameters presentParams = new PresentParameters(); //設定在視窗模式下運行 presentParams.Windowed = true; //設定交換效果為Discard presentParams.SwapEffect = SwapEffect.Discard; presentParams.AutoDepthStencilFormat = DepthFormat.D16; presentParams.EnableAutoDepthStencil = true; //建立裝置 //因為我顯示在panel1中,所以device中的第三個變數是panel的名字 device = new Device(0, DeviceType.Hardware, panel1, CreateFlags.SoftwareVertexProcessing, presentParams); //我的3D檔案在Debug中的Model檔案中,因此temp擷取了3D模型的地址 string temp = path; temp = temp + "\\Model\\Model.X"; //這個函數用於載入3D模型並且儲存在mesh中 LoadMesh(temp); }</span>
然後是載入3D模型的LoadMesh(string file) 函數
private void LoadMesh(string file) { ExtendedMaterial[] mtrl = null; //載入 try { mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl); //有材質的話,則載入 if ((mtrl != null) && (mtrl.Length > 0)) { //這兩個就是前面定義的全域變數,儲存材質和紋理 meshMaterials = new Material[mtrl.Length]; meshTextures = new Texture[mtrl.Length]; for (int i = 0; i < mtrl.Length; ++i) { /*當前的temp是Debug下的Model檔案, *Model檔案中有儲存紋理和材質的檔案 */ string temp = path + "\\Model\\"; meshMaterials[i] = mtrl[i].Material3D; if ((mtrl[i].TextureFilename != null) && mtrl[i].TextureFilename != string.Empty) { meshTextures[i] = TextureLoader.FromFile(device, temp + mtrl[i].TextureFilename); } } } } catch (Direct3DXException ex) { MessageBox.Show(ex.ToString()); return; } }
載入模型之後就需要將模型畫出來,因此,還需要一個畫模型的函數:
//繪製mesh的材質和紋理 private void DrawMesh(float yaw, float pitch, float roll, float x, float y, float z) { angle += 0.01f; device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch, roll) * Matrix.Translation(x, y, z); for (int i = 0; i < meshMaterials.Length; ++i) { //設定材質 device.Material = meshMaterials[i]; //設定紋理 device.SetTexture(0, meshTextures[i]); //繪製 mesh.DrawSubset(i); } }
最後還差一個攝影燈光的設定了,這個用於燈光的角度:
//設定網路攝影機 private void SetupCamera() { //(float)Math.PI/12設定對象大小 device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 12, this.Width / this.Height, 0.80f, 10000.0f); device.Transform.View = Matrix.LookAtLH(new Vector3(-400, -100, 600.0f), new Vector3(), new Vector3(0, 1, 0)); device.RenderState.Ambient = Color.Black; device.Lights[0].Type = LightType.Directional; device.Lights[0].Diffuse = Color.AntiqueWhite; device.Lights[0].Direction = new Vector3(0, 1, 0); device.Lights[0].Update(); device.Lights[0].Enabled = true; }
至此,基本大功告成,最後的是逐步調用這幾個函數,然後顯示出來,我採用panel這個控制項繪畫的時候調用這些函數,如下:
//panelPaint是我自己起的名字,對應的事件是Paint private void panelPaint(object sender, PaintEventArgs e) { InitializeGraphics(); device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.SkyBlue, 1.0f, 1); SetupCamera(); device.Present(); device.BeginScene(); // Draw our Mesh DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f, angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f); device.EndScene(); //Render(); device.Present(); // this.Invalidate(); }
最後貼出來一個效果圖:
至此,基本大功告成。不過這裡還有幾個問題要說明:
1.程式編譯過程中或許會遇到一個問題:
混合模式程式集是針對“v1.1.4322”版的運行時產生的,在沒有配置其他資訊的情況下,無法在 4.0 運行時中載入該程式集。
這個問題解決辦法就是開啟檔案中的app.config檔案,注釋掉原來的內容,改成以下內容:
<span style="font-size:14px;"><span style="font-family:'Microsoft YaHei';"><?xml version="1.0"?><configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/> </startup></configuration></span></span>
程式應該就不會有問題了。
2.如果你自己在匯入自己的3D模型的時候,採用3dsmax中匯入的panda控制項轉換模型檔案為.x檔案的時候,有個選項,就是XFileSetting的設定一定要設定為Binary,如果設定為Text的話,Directx在讀入檔案的時候會不識別。截圖如下:
能遇到的問題基本就這些了,這裡附上原始碼連結:
http://download.csdn.net/detail/t46414704152abc/8709251
恩,基本就這樣了。希望能協助到大家。